2004-07-21 Bernie Solomon <bernard@ugsolutions.com>
[mono.git] / mono / interpreter / interp.c
1 /*
2  * PLEASE NOTE: This is a research prototype.
3  *
4  *
5  * interp.c: Interpreter for CIL byte codes
6  *
7  * Authors:
8  *   Paolo Molaro (lupus@ximian.com)
9  *   Miguel de Icaza (miguel@ximian.com)
10  *   Dietmar Maurer (dietmar@ximian.com)
11  *
12  * (C) 2001, 2002 Ximian, Inc.
13  */
14 #ifndef __USE_ISOC99
15 #define __USE_ISOC99
16 #endif
17 #include "config.h"
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <setjmp.h>
23 #include <signal.h>
24 #include <math.h>
25 #include <locale.h>
26
27 #include <mono/os/gc_wrapper.h>
28
29 #ifdef HAVE_ALLOCA_H
30 #   include <alloca.h>
31 #else
32 #   ifdef __CYGWIN__
33 #      define alloca __builtin_alloca
34 #   endif
35 #endif
36
37 /* trim excessive headers */
38 #include <mono/metadata/image.h>
39 #include <mono/metadata/assembly.h>
40 #include <mono/metadata/cil-coff.h>
41 #include <mono/metadata/mono-endian.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/tokentype.h>
44 #include <mono/metadata/loader.h>
45 #include <mono/metadata/threads.h>
46 #include <mono/metadata/threadpool.h>
47 #include <mono/metadata/profiler-private.h>
48 #include <mono/metadata/appdomain.h>
49 #include <mono/metadata/reflection.h>
50 #include <mono/metadata/exception.h>
51 #include <mono/metadata/verify.h>
52 #include <mono/metadata/opcodes.h>
53 #include <mono/metadata/debug-helpers.h>
54 #include <mono/metadata/mono-config.h>
55 #include <mono/metadata/marshal.h>
56 #include <mono/metadata/environment.h>
57 #include <mono/metadata/mono-debug.h>
58 #include <mono/os/util.h>
59
60 #include "interp.h"
61 #include "mintops.h"
62 #include "embed.h"
63 #include "hacks.h"
64
65 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
66         a = i,
67
68 enum {
69 #include "mono/cil/opcode.def"
70         CEE_LASTOP
71 };
72 #undef OPDEF
73
74 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
75 #ifdef _WIN32
76 #define isnan _isnan
77 #define finite _finite
78 #endif
79 #ifndef HAVE_FINITE
80 #ifdef HAVE_ISFINITE
81 #define finite isfinite
82 #endif
83 #endif
84
85 static gint *abort_requested;
86
87 /* If true, then we output the opcodes as we interpret them */
88 static int global_tracing = 0;
89 static int global_no_pointers = 0;
90
91 int mono_interp_traceopt = 0;
92
93 static int debug_indent_level = 0;
94
95 #define INIT_FRAME(frame,parent_frame,obj_this,method_args,method_retval,mono_method)   \
96         do {    \
97                 (frame)->parent = (parent_frame);       \
98                 (frame)->obj = (obj_this);      \
99                 (frame)->stack_args = (method_args);    \
100                 (frame)->retval = (method_retval);      \
101                 (frame)->runtime_method = mono_interp_get_runtime_method (mono_method); \
102                 (frame)->ex = NULL;     \
103                 (frame)->ip = NULL;     \
104                 (frame)->invoke_trap = 0;       \
105         } while (0)
106
107 void ves_exec_method (MonoInvocation *frame);
108
109 static char* dump_stack (stackval *stack, stackval *sp);
110 static char* dump_frame (MonoInvocation *inv);
111 static MonoArray *get_trace_ips (MonoDomain *domain, MonoInvocation *top);
112 static void ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
113
114 typedef void (*ICallMethod) (MonoInvocation *frame);
115
116 static guint32 die_on_exception = 0;
117 static guint32 thread_context_id = 0;
118
119 #define DEBUG_INTERP 1
120 #define COUNT_OPS 0
121 #if DEBUG_INTERP
122
123 static int break_on_method = 0;
124 static int nested_trace = 0;
125 static GList *db_methods = NULL;
126
127 static void
128 output_indent (void)
129 {
130         int h;
131
132         for (h = 0; h < debug_indent_level; h++)
133                 g_print ("  ");
134 }
135
136 static void
137 db_match_method (gpointer data, gpointer user_data)
138 {
139         MonoMethod *m = (MonoMethod*)user_data;
140         MonoMethodDesc *desc = data;
141
142         if (mono_method_desc_full_match (desc, m))
143                 break_on_method = 1;
144 }
145
146 #define DEBUG_ENTER()   \
147         if (db_methods) { \
148                 g_list_foreach (db_methods, db_match_method, (gpointer)frame->runtime_method->method);  \
149                 if (break_on_method) tracing=nested_trace ? (global_tracing = 2, 3) : 2;        \
150                 break_on_method = 0;    \
151         } \
152         if (tracing) {  \
153                 MonoMethod *method = frame->runtime_method->method ;\
154                 char *mn, *args = dump_args (frame);    \
155                 debug_indent_level++;   \
156                 output_indent ();       \
157                 mn = mono_method_full_name (method, FALSE); \
158                 g_print ("(%u) Entering %s (", GetCurrentThreadId(), mn);       \
159                 g_free (mn); \
160                 g_print ("%s)\n", args);        \
161                 g_free (args);  \
162         }       \
163         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
164                 mono_profiler_method_enter (frame->runtime_method->method);
165
166 #define DEBUG_LEAVE()   \
167         if (tracing) {  \
168                 char *mn, *args;        \
169                 args = dump_retval (frame);     \
170                 output_indent ();       \
171                 mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
172                 g_print ("(%u) Leaving %s", GetCurrentThreadId(),  mn); \
173                 g_free (mn); \
174                 g_print (" => %s\n", args);     \
175                 g_free (args);  \
176                 debug_indent_level--;   \
177                 if (tracing == 3) global_tracing = 0; \
178         }       \
179         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
180                 mono_profiler_method_leave (frame->runtime_method->method);
181
182 #else
183
184 #define DEBUG_ENTER()
185 #define DEBUG_LEAVE()
186
187 #endif
188
189 static void
190 interp_ex_handler (MonoException *ex) {
191         ThreadContext *context = TlsGetValue (thread_context_id);
192         char *stack_trace;
193         if (context == NULL)
194                 return;
195         stack_trace = dump_frame (context->current_frame);
196         ex->stack_trace = mono_string_new (mono_domain_get(), stack_trace);
197         g_free (stack_trace);
198         if (context->current_env == NULL || strcmp(ex->object.vtable->klass->name, "ExecutionEngineException") == 0) {
199                 char *strace = mono_string_to_utf8 (ex->stack_trace);
200                 fprintf(stderr, "Nothing can catch this exception: ");
201                 fprintf(stderr, "%s", ex->object.vtable->klass->name);
202                 if (ex->message != NULL) {
203                         char *m = mono_string_to_utf8 (ex->message);
204                         fprintf(stderr, ": %s", m);
205                         g_free(m);
206                 }
207                 fprintf(stderr, "\n");
208                 fprintf(stderr, "%s\n", strace);
209                 g_free (strace);
210                 if (ex->inner_ex != NULL) {
211                         ex = (MonoException *)ex->inner_ex;
212                         fprintf(stderr, "Inner exception: %s", ex->object.vtable->klass->name);
213                         if (ex->message != NULL) {
214                                 char *m = mono_string_to_utf8 (ex->message);
215                                 fprintf(stderr, ": %s", m);
216                                 g_free(m);
217                         }
218                         strace = mono_string_to_utf8 (ex->stack_trace);
219                         fprintf(stderr, "\n");
220                         fprintf(stderr, "%s\n", strace);
221                         g_free (strace);
222                 }
223                 /* wait for other threads to also collapse */
224                 Sleep(1000);
225                 exit(1);
226         }
227         context->env_frame->ex = ex;
228         context->search_for_handler = 1;
229         longjmp (*context->current_env, 1);
230 }
231
232 static void
233 ves_real_abort (int line, MonoMethod *mh,
234                 const unsigned short *ip, stackval *stack, stackval *sp)
235 {
236         MonoMethodNormal *mm = (MonoMethodNormal *)mh;
237         fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
238         fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
239                  ip-(const unsigned short *)mm->header->code);
240         g_print ("0x%04x %02x\n",
241                  ip-(const unsigned short *)mm->header->code, *ip);
242         if (sp > stack)
243                 printf ("\t[%d] 0x%08x %0.5f\n", sp-stack, sp[-1].data.i, sp[-1].data.f);
244 }
245
246 #define ves_abort() \
247         do {\
248                 ves_real_abort(__LINE__, frame->runtime_method->method, ip, frame->stack, sp); \
249                 THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
250         } while (0);
251
252 static gpointer
253 interp_create_remoting_trampoline (MonoMethod *method)
254 {
255         return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke (method));
256 }
257
258 static CRITICAL_SECTION runtime_method_lookup_section;
259
260 RuntimeMethod*
261 mono_interp_get_runtime_method (MonoMethod *method)
262 {
263         MonoDomain *domain = mono_domain_get ();
264         RuntimeMethod *rtm;
265
266         EnterCriticalSection (&runtime_method_lookup_section);
267         if ((rtm = g_hash_table_lookup (domain->jit_code_hash, method))) {
268                 LeaveCriticalSection (&runtime_method_lookup_section);
269                 return rtm;
270         }
271         rtm = mono_mempool_alloc (domain->mp, sizeof (RuntimeMethod));
272         memset (rtm, 0, sizeof (*rtm));
273         rtm->method = method;
274         rtm->param_count = method->signature->param_count;
275         rtm->hasthis = method->signature->hasthis;
276         rtm->valuetype = method->klass->valuetype;
277         g_hash_table_insert (domain->jit_code_hash, method, rtm);
278         LeaveCriticalSection (&runtime_method_lookup_section);
279
280         return rtm;
281 }
282
283 static gpointer
284 interp_create_trampoline (MonoMethod *method)
285 {
286         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
287                 method = mono_marshal_get_synchronized_wrapper (method);
288         return mono_interp_get_runtime_method (method);
289 }
290
291 static inline RuntimeMethod*
292 get_virtual_method (RuntimeMethod *runtime_method, MonoObject *obj)
293 {
294         MonoMethod *m = runtime_method->method;
295
296         if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
297                 if (obj->vtable->klass == mono_defaults.transparent_proxy_class) 
298                         return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke (m));
299                 else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
300                         return mono_interp_get_runtime_method (mono_marshal_get_synchronized_wrapper (m));
301                 else
302                         return runtime_method;
303         }
304
305         if (m->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
306                 return ((RuntimeMethod **)obj->vtable->interface_offsets [m->klass->interface_id]) [m->slot];
307         } else {
308                 return ((RuntimeMethod **)obj->vtable->vtable) [m->slot];
309         }
310 }
311
312 void inline
313 stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke)
314 {
315         if (type->byref) {
316                 switch (type->type) {
317                 case MONO_TYPE_OBJECT:
318                 case MONO_TYPE_CLASS:
319                 case MONO_TYPE_STRING:
320                 case MONO_TYPE_ARRAY:
321                 case MONO_TYPE_SZARRAY:
322                         break;
323                 default:
324                         break;
325                 }
326                 result->data.p = *(gpointer*)data;
327                 return;
328         }
329         switch (type->type) {
330         case MONO_TYPE_VOID:
331                 return;
332         case MONO_TYPE_I1:
333                 result->data.i = *(gint8*)data;
334                 return;
335         case MONO_TYPE_U1:
336         case MONO_TYPE_BOOLEAN:
337                 result->data.i = *(guint8*)data;
338                 return;
339         case MONO_TYPE_I2:
340                 result->data.i = *(gint16*)data;
341                 return;
342         case MONO_TYPE_U2:
343         case MONO_TYPE_CHAR:
344                 result->data.i = *(guint16*)data;
345                 return;
346         case MONO_TYPE_I4:
347                 result->data.i = *(gint32*)data;
348                 return;
349         case MONO_TYPE_U:
350         case MONO_TYPE_I:
351                 result->data.nati = *(mono_i*)data;
352                 return;
353         case MONO_TYPE_PTR:
354                 result->data.p = *(gpointer*)data;
355                 return;
356         case MONO_TYPE_U4:
357                 result->data.i = *(guint32*)data;
358                 return;
359         case MONO_TYPE_R4:
360                 result->data.f = *(float*)data;
361                 return;
362         case MONO_TYPE_I8:
363         case MONO_TYPE_U8:
364                 result->data.l = *(gint64*)data;
365                 return;
366         case MONO_TYPE_R8:
367                 result->data.f = *(double*)data;
368                 return;
369         case MONO_TYPE_STRING:
370         case MONO_TYPE_SZARRAY:
371         case MONO_TYPE_CLASS:
372         case MONO_TYPE_OBJECT:
373         case MONO_TYPE_ARRAY:
374                 result->data.p = *(gpointer*)data;
375                 return;
376         case MONO_TYPE_VALUETYPE:
377                 if (type->data.klass->enumtype) {
378                         stackval_from_data (type->data.klass->enum_basetype, result, data, pinvoke);
379                         return;
380                 } else {
381                         int size;
382                         
383                         if (pinvoke)
384                                 size = mono_class_native_size (type->data.klass, NULL);
385                         else
386                                 size = mono_class_value_size (type->data.klass, NULL);
387                         memcpy (result->data.vt, data, size);
388                 }
389                 return;
390         default:
391                 g_warning ("got type 0x%02x", type->type);
392                 g_assert_not_reached ();
393         }
394 }
395
396 void inline
397 stackval_to_data (MonoType *type, stackval *val, char *data, gboolean pinvoke)
398 {
399         if (type->byref) {
400                 gpointer *p = (gpointer*)data;
401                 *p = val->data.p;
402                 return;
403         }
404         /* printf ("TODAT0 %p\n", data); */
405         switch (type->type) {
406         case MONO_TYPE_I1:
407         case MONO_TYPE_U1: {
408                 guint8 *p = (guint8*)data;
409                 *p = val->data.i;
410                 return;
411         }
412         case MONO_TYPE_BOOLEAN: {
413                 guint8 *p = (guint8*)data;
414                 *p = (val->data.i != 0);
415                 return;
416         }
417         case MONO_TYPE_I2:
418         case MONO_TYPE_U2:
419         case MONO_TYPE_CHAR: {
420                 guint16 *p = (guint16*)data;
421                 *p = val->data.i;
422                 return;
423         }
424         case MONO_TYPE_I: {
425                 mono_i *p = (mono_i*)data;
426                 /* In theory the value used by stloc should match the local var type
427                    but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
428                    a native int - both by csc and mcs). Not sure what to do about sign extension
429                    as it is outside the spec... doing the obvious */
430                 *p = (mono_i)val->data.nati;
431                 return;
432         }
433         case MONO_TYPE_U: {
434                 mono_u *p = (mono_u*)data;
435                 /* see above. */
436                 *p = (mono_u)val->data.nati;
437                 return;
438         }
439         case MONO_TYPE_I4:
440         case MONO_TYPE_U4: {
441                 gint32 *p = (gint32*)data;
442                 *p = val->data.i;
443                 return;
444         }
445         case MONO_TYPE_I8:
446         case MONO_TYPE_U8: {
447                 gint64 *p = (gint64*)data;
448                 *p = val->data.l;
449                 return;
450         }
451         case MONO_TYPE_R4: {
452                 float *p = (float*)data;
453                 *p = val->data.f;
454                 return;
455         }
456         case MONO_TYPE_R8: {
457                 double *p = (double*)data;
458                 *p = val->data.f;
459                 return;
460         }
461         case MONO_TYPE_STRING:
462         case MONO_TYPE_SZARRAY:
463         case MONO_TYPE_CLASS:
464         case MONO_TYPE_OBJECT:
465         case MONO_TYPE_ARRAY:
466         case MONO_TYPE_PTR: {
467                 gpointer *p = (gpointer*)data;
468                 *p = val->data.p;
469                 return;
470         }
471         case MONO_TYPE_VALUETYPE:
472                 if (type->data.klass->enumtype) {
473                         stackval_to_data (type->data.klass->enum_basetype, val, data, pinvoke);
474                         return;
475                 } else {
476                         int size;
477
478                         if (pinvoke)
479                                 size = mono_class_native_size (type->data.klass, NULL);
480                         else
481                                 size = mono_class_value_size (type->data.klass, NULL);
482
483                         memcpy (data, val->data.p, size);
484                 }
485                 return;
486         default:
487                 g_warning ("got type %x", type->type);
488                 g_assert_not_reached ();
489         }
490 }
491
492 static void
493 fill_in_trace (MonoException *exception, MonoInvocation *frame)
494 {
495         char *stack_trace = dump_frame (frame);
496         MonoDomain *domain = mono_domain_get();
497         (exception)->stack_trace = mono_string_new (domain, stack_trace);
498         (exception)->trace_ips = get_trace_ips (domain, frame);
499         g_free (stack_trace);
500 }
501
502 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
503
504 #define THROW_EX(exception,ex_ip)       \
505         do {\
506                 frame->ip = (ex_ip);            \
507                 frame->ex = (MonoException*)(exception);        \
508                 FILL_IN_TRACE(frame->ex, frame); \
509                 goto handle_exception;  \
510         } while (0)
511
512 static MonoObject*
513 ves_array_create (MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
514 {
515         guint32 *lengths;
516         guint32 *lower_bounds;
517         int i;
518
519         lengths = alloca (sizeof (guint32) * klass->rank * 2);
520         for (i = 0; i < sig->param_count; ++i) {
521                 lengths [i] = values->data.i;
522                 values ++;
523         }
524         if (klass->rank == sig->param_count) {
525                 /* Only lengths provided. */
526                 lower_bounds = NULL;
527         } else {
528                 /* lower bounds are first. */
529                 lower_bounds = lengths;
530                 lengths += klass->rank;
531         }
532         return (MonoObject*)mono_array_new_full (domain, klass, lengths, lower_bounds);
533 }
534
535 static void 
536 ves_array_set (MonoInvocation *frame)
537 {
538         stackval *sp = frame->stack_args;
539         MonoObject *o;
540         MonoArray *ao;
541         MonoClass *ac;
542         gint32 i, t, pos, esize;
543         gpointer ea;
544         MonoType *mt;
545
546         o = frame->obj;
547         ao = (MonoArray *)o;
548         ac = o->vtable->klass;
549
550         g_assert (ac->rank >= 1);
551
552         pos = sp [0].data.i;
553         if (ao->bounds != NULL) {
554                 pos -= ao->bounds [0].lower_bound;
555                 for (i = 1; i < ac->rank; i++) {
556                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
557                             ao->bounds [i].length) {
558                                 frame->ex = mono_get_exception_index_out_of_range ();
559                                 FILL_IN_TRACE(frame->ex, frame);
560                                 return;
561                         }
562                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
563                                 ao->bounds [i].lower_bound;
564                 }
565         } else if (pos >= ao->max_length) {
566                 frame->ex = mono_get_exception_index_out_of_range ();
567                 FILL_IN_TRACE(frame->ex, frame);
568                 return;
569         }
570
571 #if 0 /* FIX */
572         if (sp [ac->rank].data.p && !mono_object_isinst (sp [ac->rank].data.p, mono_object_class (o)->element_class)) {
573                 frame->ex = mono_get_exception_array_type_mismatch ();
574                 FILL_IN_TRACE (frame->ex, frame);
575                 return;
576         }
577 #endif
578
579         esize = mono_array_element_size (ac);
580         ea = mono_array_addr_with_size (ao, esize, pos);
581
582         mt = frame->runtime_method->method->signature->params [ac->rank];
583         stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
584 }
585
586 static void 
587 ves_array_get (MonoInvocation *frame)
588 {
589         stackval *sp = frame->stack_args;
590         MonoObject *o;
591         MonoArray *ao;
592         MonoClass *ac;
593         gint32 i, t, pos, esize;
594         gpointer ea;
595         MonoType *mt;
596
597         o = frame->obj;
598         ao = (MonoArray *)o;
599         ac = o->vtable->klass;
600
601         g_assert (ac->rank >= 1);
602
603         pos = sp [0].data.i;
604         if (ao->bounds != NULL) {
605                 pos -= ao->bounds [0].lower_bound;
606                 for (i = 1; i < ac->rank; i++) {
607                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
608                             ao->bounds [i].length) {
609                                 frame->ex = mono_get_exception_index_out_of_range ();
610                                 FILL_IN_TRACE(frame->ex, frame);
611                                 return;
612                         }
613
614                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
615                                 ao->bounds [i].lower_bound;
616                 }
617         } else if (pos >= ao->max_length) {
618                 frame->ex = mono_get_exception_index_out_of_range ();
619                 FILL_IN_TRACE(frame->ex, frame);
620                 return;
621         }
622
623         esize = mono_array_element_size (ac);
624         ea = mono_array_addr_with_size (ao, esize, pos);
625
626         mt = frame->runtime_method->method->signature->ret;
627         stackval_from_data (mt, frame->retval, ea, FALSE);
628 }
629
630 static void
631 ves_array_element_address (MonoInvocation *frame)
632 {
633         stackval *sp = frame->stack_args;
634         MonoObject *o;
635         MonoArray *ao;
636         MonoClass *ac;
637         gint32 i, t, pos, esize;
638         gpointer ea;
639
640         o = frame->obj;
641         ao = (MonoArray *)o;
642         ac = o->vtable->klass;
643
644         g_assert (ac->rank >= 1);
645
646         pos = sp [0].data.i;
647         if (ao->bounds != NULL) {
648                 pos -= ao->bounds [0].lower_bound;
649                 for (i = 1; i < ac->rank; i++) {
650                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
651                             ao->bounds [i].length) {
652                                 frame->ex = mono_get_exception_index_out_of_range ();
653                                 FILL_IN_TRACE(frame->ex, frame);
654                                 return;
655                         }
656                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
657                                 ao->bounds [i].lower_bound;
658                 }
659         } else if (pos >= ao->max_length) {
660                 frame->ex = mono_get_exception_index_out_of_range ();
661                 FILL_IN_TRACE(frame->ex, frame);
662                 return;
663         }
664
665         esize = mono_array_element_size (ac);
666         ea = mono_array_addr_with_size (ao, esize, pos);
667
668         frame->retval->data.p = ea;
669 }
670
671 static void
672 interp_walk_stack (MonoStackWalk func, gpointer user_data)
673 {
674         ThreadContext *context = TlsGetValue (thread_context_id);
675         MonoInvocation *frame = context->current_frame;
676         int il_offset;
677         MonoMethodHeader *hd;
678
679         while (frame) {
680                 gboolean managed = FALSE;
681                 MonoMethod *method = frame->runtime_method->method;
682                 if (!method || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || 
683                                 (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
684                         il_offset = -1;
685                 else {
686                         hd = ((MonoMethodNormal*)method)->header;
687                         il_offset = frame->ip - (const unsigned short *)hd->code;
688                         if (!method->wrapper_type)
689                                 managed = TRUE;
690                 }
691                 if (func (method, -1, il_offset, managed, user_data))
692                         return;
693                 frame = frame->parent;
694         }
695 }
696
697 static void 
698 ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFunc addr, gboolean string_ctor, ThreadContext *context)
699 {
700         jmp_buf env;
701         MonoPIFunc func;
702         MonoInvocation *old_frame = context->current_frame;
703         MonoInvocation *old_env_frame = context->env_frame;
704         jmp_buf *old_env = context->current_env;
705
706         if (setjmp (env)) {
707                 context->current_frame = old_frame;
708                 context->env_frame = old_env_frame;
709                 context->current_env = old_env;
710                 context->managed_code = 1;
711                 return;
712         }
713
714         frame->ex = NULL;
715         context->env_frame = frame;
716         context->current_env = &env;
717
718         if (frame->runtime_method) {
719                 func = frame->runtime_method->func;
720         } else {
721                 func = mono_arch_create_trampoline (sig, string_ctor);
722         }
723
724         context->current_frame = frame;
725         context->managed_code = 0;
726
727         func (addr, &frame->retval->data.p, frame->obj, frame->stack_args);
728
729         context->managed_code = 1;
730         /* domain can only be changed by native code */
731         context->domain = mono_domain_get ();
732
733         if (*abort_requested)
734                 mono_thread_interruption_checkpoint ();
735         
736         if (string_ctor) {
737                 stackval_from_data (&mono_defaults.string_class->byval_arg, 
738                                     frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
739         } else if (!MONO_TYPE_ISSTRUCT (sig->ret))
740                 stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
741
742         context->current_frame = old_frame;
743         context->env_frame = old_env_frame;
744         context->current_env = old_env;
745 }
746
747 static void
748 interp_delegate_ctor (MonoDomain *domain, MonoObject *this, MonoObject *target, RuntimeMethod *runtime_method)
749 {
750         MonoDelegate *delegate = (MonoDelegate *)this;
751
752         delegate->method_info = mono_method_get_object (domain, runtime_method->method, NULL);
753         delegate->target = target;
754
755         if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
756                 MonoMethod *method = mono_marshal_get_remoting_invoke (runtime_method->method);
757                 delegate->method_ptr = mono_interp_get_runtime_method (method);
758         } else {
759                 delegate->method_ptr = runtime_method;
760         }
761 }
762
763 /*
764  * From the spec:
765  * runtime specifies that the implementation of the method is automatically
766  * provided by the runtime and is primarily used for the methods of delegates.
767  */
768 static void
769 ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
770 {
771         MonoMethod *method = frame->runtime_method->method;
772         const char *name = method->name;
773         MonoObject *obj = (MonoObject*)frame->obj;
774
775         mono_class_init (method->klass);
776         
777         if (obj && mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
778                 if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
779                         interp_delegate_ctor (context->domain, obj, frame->stack_args[0].data.p, frame->stack_args[1].data.p);
780                         return;
781                 }
782         }
783
784         if (obj && mono_object_isinst (obj, mono_defaults.array_class)) {
785                 if (*name == 'S' && (strcmp (name, "Set") == 0)) {
786                         ves_array_set (frame);
787                         return;
788                 }
789                 if (*name == 'G' && (strcmp (name, "Get") == 0)) {
790                         ves_array_get (frame);
791                         return;
792                 }
793                 if (*name == 'A' && (strcmp (name, "Address") == 0)) {
794                         ves_array_element_address (frame);
795                         return;
796                 }
797         }
798         
799         g_error ("Don't know how to exec runtime method %s.%s::%s", 
800                         method->klass->name_space, method->klass->name,
801                         method->name);
802 }
803
804 static char*
805 dump_stack (stackval *stack, stackval *sp)
806 {
807         stackval *s = stack;
808         GString *str = g_string_new ("");
809         
810         if (sp == stack)
811                 return g_string_free (str, FALSE);
812         
813         while (s < sp) {
814                 g_string_sprintfa (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
815                 ++s;
816         }
817         return g_string_free (str, FALSE);
818 }
819
820 static void
821 dump_stackval (GString *str, stackval *s, MonoType *type)
822 {
823         switch (type->type) {
824         case MONO_TYPE_I1:
825         case MONO_TYPE_U1:
826         case MONO_TYPE_I2:
827         case MONO_TYPE_U2:
828         case MONO_TYPE_I4:
829         case MONO_TYPE_U4:
830         case MONO_TYPE_CHAR:
831         case MONO_TYPE_BOOLEAN:
832                 g_string_sprintfa (str, "[%d] ", s->data.i);
833                 break;
834         case MONO_TYPE_STRING:
835         case MONO_TYPE_SZARRAY:
836         case MONO_TYPE_CLASS:
837         case MONO_TYPE_OBJECT:
838         case MONO_TYPE_ARRAY:
839         case MONO_TYPE_PTR:
840         case MONO_TYPE_I:
841         case MONO_TYPE_U:
842                 g_string_sprintfa (str, "[%p] ", s->data.p);
843                 break;
844         case MONO_TYPE_VALUETYPE:
845                 if (type->data.klass->enumtype)
846                         g_string_sprintfa (str, "[%d] ", s->data.i);
847                 else
848                         g_string_sprintfa (str, "[vt:%p] ", s->data.p);
849                 break;
850         case MONO_TYPE_R4:
851         case MONO_TYPE_R8:
852                 g_string_sprintfa (str, "[%g] ", s->data.f);
853                 break;
854         case MONO_TYPE_I8:
855         case MONO_TYPE_U8:
856         default:
857                 g_string_sprintfa (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
858                 break;
859         }
860 }
861
862 static char*
863 dump_args (MonoInvocation *inv)
864 {
865         GString *str = g_string_new ("");
866         int i;
867         MonoMethodSignature *signature = inv->runtime_method->method->signature;
868         
869         if (signature->param_count == 0)
870                 return g_string_free (str, FALSE);
871
872         if (signature->hasthis)
873                 g_string_sprintfa (str, "%p ", inv->obj);
874
875         for (i = 0; i < signature->param_count; ++i)
876                 dump_stackval (str, inv->stack_args + i, signature->params [i]);
877
878         return g_string_free (str, FALSE);
879 }
880
881 static char*
882 dump_retval (MonoInvocation *inv)
883 {
884         GString *str = g_string_new ("");
885         MonoType *ret = inv->runtime_method->method->signature->ret;
886
887         if (ret->type != MONO_TYPE_VOID)
888                 dump_stackval (str, inv->retval, ret);
889
890         return g_string_free (str, FALSE);
891 }
892  
893 static char*
894 dump_frame (MonoInvocation *inv)
895 {
896         GString *str = g_string_new ("");
897         int i;
898         char *args;
899         for (i = 0; inv; inv = inv->parent) {
900                 if (inv->runtime_method != NULL) {
901                         MonoMethod *method = inv->runtime_method->method;
902                         MonoClass *k;
903
904                         int codep = 0;
905                         const char * opname = "";
906                         char *name;
907                         gchar *source = NULL;
908
909                         k = method->klass;
910
911                         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
912                                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
913                                 MonoMethodHeader *hd = ((MonoMethodNormal *)method)->header;
914
915                                 if (hd != NULL) {
916                                         if (inv->ip) {
917                                                 opname = mono_interp_opname [*inv->ip];
918                                                 codep = inv->ip - inv->runtime_method->code;
919                                         } else 
920                                                 opname = "";
921         
922                                         source = mono_debug_source_location_from_il_offset (method, codep, NULL);
923                                 }
924                         }
925                         args = dump_args (inv);
926                         name = mono_method_full_name (method, TRUE);
927                         if (source)
928                                 g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s (%s) at %s\n", i, codep, opname,
929                                                    name, args, source);
930                         else
931                                 g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s (%s)\n", i, codep, opname,
932                                                    name, args);
933                         g_free (name);
934                         g_free (args);
935                         g_free (source);
936                         ++i;
937                 }
938         }
939         return g_string_free (str, FALSE);
940 }
941
942 static MonoArray *
943 get_trace_ips (MonoDomain *domain, MonoInvocation *top)
944 {
945         int i;
946         MonoArray *res;
947         MonoInvocation *inv;
948
949         for (i = 0, inv = top; inv; inv = inv->parent)
950                 if (inv->runtime_method != NULL)
951                         ++i;
952
953         res = mono_array_new (domain, mono_defaults.int_class, 2 * i);
954
955         for (i = 0, inv = top; inv; inv = inv->parent)
956                 if (inv->runtime_method != NULL) {
957                         mono_array_set (res, gpointer, i, inv->runtime_method);
958                         ++i;
959                         mono_array_set (res, gpointer, i, (gpointer)inv->ip);
960                         ++i;
961                 }
962
963         return res;
964 }
965
966
967 #define MYGUINT64_MAX 18446744073709551615ULL
968 #define MYGINT64_MAX 9223372036854775807LL
969 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
970
971 #define MYGUINT32_MAX 4294967295U
972 #define MYGINT32_MAX 2147483647
973 #define MYGINT32_MIN (-MYGINT32_MAX -1)
974         
975 #define CHECK_ADD_OVERFLOW(a,b) \
976         (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0  \
977         : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
978
979 #define CHECK_SUB_OVERFLOW(a,b) \
980         (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0   \
981         : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
982
983 #define CHECK_ADD_OVERFLOW_UN(a,b) \
984         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
985
986 #define CHECK_SUB_OVERFLOW_UN(a,b) \
987         (guint32)(a) < (guint32)(b) ? -1 : 0
988
989 #define CHECK_ADD_OVERFLOW64(a,b) \
990         (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0  \
991         : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
992
993 #define CHECK_SUB_OVERFLOW64(a,b) \
994         (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0   \
995         : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
996
997 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
998         (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
999
1000 #define CHECK_SUB_OVERFLOW64_UN(a,b) \
1001         (guint64)(a) < (guint64)(b) ? -1 : 0
1002
1003 #if SIZEOF_VOID_P == 4
1004 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
1005 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
1006 #else
1007 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
1008 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
1009 #endif
1010
1011 /* Resolves to TRUE if the operands would overflow */
1012 #define CHECK_MUL_OVERFLOW(a,b) \
1013         ((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
1014         (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
1015         (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
1016         (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
1017         (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
1018         (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
1019         (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
1020
1021 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1022         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1023         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1024
1025 #define CHECK_MUL_OVERFLOW64(a,b) \
1026         ((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
1027         (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
1028         (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
1029         (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
1030         (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
1031         (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
1032         (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
1033
1034 #define CHECK_MUL_OVERFLOW64_UN(a,b) \
1035         ((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
1036         (guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
1037
1038 #if SIZEOF_VOID_P == 4
1039 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
1040 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
1041 #else
1042 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
1043 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
1044 #endif
1045
1046 static MonoObject*
1047 interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1048 {
1049         MonoInvocation frame;
1050         ThreadContext * volatile context = TlsGetValue (thread_context_id);
1051         MonoObject *retval = NULL;
1052         MonoMethodSignature *sig = method->signature;
1053         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1054         int i, type, isobject = 0;
1055         void *ret = NULL;
1056         stackval result;
1057         stackval *args = alloca (sizeof (stackval) * sig->param_count);
1058         ThreadContext context_struct;
1059         MonoInvocation *old_frame = NULL;
1060         jmp_buf env;
1061
1062         frame.ex = NULL;
1063
1064         if (setjmp(env)) {
1065                 if (context != &context_struct) {
1066                         context->domain = mono_domain_get ();
1067                         context->current_frame = old_frame;
1068                         context->managed_code = 0;
1069                 } else 
1070                         TlsSetValue (thread_context_id, NULL);
1071                 if (exc != NULL)
1072                         *exc = (MonoObject *)frame.ex;
1073                 return retval;
1074         }
1075
1076         if (context == NULL) {
1077                 context = &context_struct;
1078                 context_struct.base_frame = &frame;
1079                 context_struct.current_frame = NULL;
1080                 context_struct.env_frame = &frame;
1081                 context_struct.current_env = &env;
1082                 context_struct.search_for_handler = 0;
1083                 context_struct.managed_code = 0;
1084                 TlsSetValue (thread_context_id, context);
1085         }
1086         else
1087                 old_frame = context->current_frame;
1088
1089         context->domain = mono_domain_get ();
1090
1091         switch (sig->ret->type) {
1092         case MONO_TYPE_VOID:
1093                 break;
1094         case MONO_TYPE_STRING:
1095         case MONO_TYPE_OBJECT:
1096         case MONO_TYPE_CLASS:
1097         case MONO_TYPE_ARRAY:
1098         case MONO_TYPE_SZARRAY:
1099                 isobject = 1;
1100                 break;
1101         case MONO_TYPE_VALUETYPE:
1102                 retval = mono_object_new (context->domain, klass);
1103                 ret = ((char*)retval) + sizeof (MonoObject);
1104                 if (!sig->ret->data.klass->enumtype)
1105                         result.data.vt = ret;
1106                 break;
1107         default:
1108                 retval = mono_object_new (context->domain, klass);
1109                 ret = ((char*)retval) + sizeof (MonoObject);
1110                 break;
1111         }
1112
1113         for (i = 0; i < sig->param_count; ++i) {
1114                 if (sig->params [i]->byref) {
1115                         args [i].data.p = params [i];
1116                         continue;
1117                 }
1118                 type = sig->params [i]->type;
1119 handle_enum:
1120                 switch (type) {
1121                 case MONO_TYPE_U1:
1122                 case MONO_TYPE_I1:
1123                 case MONO_TYPE_BOOLEAN:
1124                         args [i].data.i = *(MonoBoolean*)params [i];
1125                         break;
1126                 case MONO_TYPE_U2:
1127                 case MONO_TYPE_I2:
1128                 case MONO_TYPE_CHAR:
1129                         args [i].data.i = *(gint16*)params [i];
1130                         break;
1131 #if SIZEOF_VOID_P == 4
1132                 case MONO_TYPE_U: /* use VAL_POINTER? */
1133                 case MONO_TYPE_I:
1134 #endif
1135                 case MONO_TYPE_U4:
1136                 case MONO_TYPE_I4:
1137                         args [i].data.i = *(gint32*)params [i];
1138                         break;
1139 #if SIZEOF_VOID_P == 8
1140                 case MONO_TYPE_U:
1141                 case MONO_TYPE_I:
1142 #endif
1143                 case MONO_TYPE_U8:
1144                 case MONO_TYPE_I8:
1145                         args [i].data.l = *(gint64*)params [i];
1146                         break;
1147                 case MONO_TYPE_VALUETYPE:
1148                         if (sig->params [i]->data.klass->enumtype) {
1149                                 type = sig->params [i]->data.klass->enum_basetype->type;
1150                                 goto handle_enum;
1151                         } else {
1152                                 args [i].data.p = params [i];
1153                         }
1154                         break;
1155                 case MONO_TYPE_STRING:
1156                 case MONO_TYPE_CLASS:
1157                 case MONO_TYPE_ARRAY:
1158                 case MONO_TYPE_SZARRAY:
1159                 case MONO_TYPE_OBJECT:
1160                         args [i].data.p = params [i];
1161                         break;
1162                 default:
1163                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1164                 }
1165         }
1166
1167         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
1168                 method = mono_marshal_get_native_wrapper (method);
1169         INIT_FRAME(&frame,context->current_frame,obj,args,&result,method);
1170         if (exc)
1171                 frame.invoke_trap = 1;
1172         context->managed_code = 1;
1173         ves_exec_method_with_context (&frame, context);
1174         context->managed_code = 0;
1175         if (context == &context_struct)
1176                 TlsSetValue (thread_context_id, NULL);
1177         else
1178                 context->current_frame = old_frame;
1179         if (frame.ex != NULL) {
1180                 if (exc != NULL) {
1181                         *exc = (MonoObject*) frame.ex;
1182                         return NULL;
1183                 }
1184                 if (context->current_env != NULL) {
1185                         context->env_frame->ex = frame.ex;
1186                         longjmp(*context->current_env, 1);
1187                 }
1188                 else
1189                         printf("dropped exception...\n");
1190         }
1191         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1192                 return NULL;
1193         if (isobject || method->string_ctor)
1194                 return result.data.p;
1195         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1196         return retval;
1197 }
1198
1199 static CRITICAL_SECTION create_method_pointer_mutex;
1200
1201 static MonoGHashTable *method_pointer_hash = NULL;
1202
1203 static void *
1204 mono_create_method_pointer (MonoMethod *method)
1205 {
1206         gpointer addr;
1207         MonoJitInfo *ji;
1208
1209         EnterCriticalSection (&create_method_pointer_mutex);
1210         if (!method_pointer_hash) {
1211                 MONO_GC_REGISTER_ROOT (method_pointer_hash);
1212                 method_pointer_hash = mono_g_hash_table_new (NULL, NULL);
1213         }
1214         addr = mono_g_hash_table_lookup (method_pointer_hash, method);
1215         if (addr) {
1216                 LeaveCriticalSection (&create_method_pointer_mutex);
1217                 return addr;
1218         }
1219
1220         /*
1221          * If it is a static P/Invoke method, we can just return the pointer
1222          * to the method implementation.
1223          */
1224         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && method->addr) {
1225                 ji = g_new0 (MonoJitInfo, 1);
1226                 ji->method = method;
1227                 ji->code_size = 1;
1228                 ji->code_start = method->addr;
1229
1230                 mono_jit_info_table_add (mono_get_root_domain (), ji);
1231                 
1232                 addr = method->addr;
1233         }               
1234         else
1235                 addr = mono_arch_create_method_pointer (method);
1236
1237         mono_g_hash_table_insert (method_pointer_hash, method, addr);
1238         LeaveCriticalSection (&create_method_pointer_mutex);
1239
1240         return addr;
1241 }
1242
1243 #if COUNT_OPS
1244 static int opcode_counts[512];
1245
1246 #define COUNT_OP(op) opcode_counts[op]++
1247 #else
1248 #define COUNT_OP(op) 
1249 #endif
1250
1251 #if DEBUG_INTERP
1252 #define DUMP_INSTR() \
1253         if (tracing > 1) { \
1254                 char *ins; \
1255                 if (sp > frame->stack) { \
1256                         ins = dump_stack (frame->stack, sp); \
1257                 } else { \
1258                         ins = g_strdup (""); \
1259                 } \
1260                 sp->data.l = 0; \
1261                 output_indent (); \
1262                 g_print ("(%u) ", GetCurrentThreadId()); \
1263                 mono_interp_dis_mintop(rtm->code, ip); \
1264                 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
1265                 g_free (ins); \
1266         }
1267 #else
1268 #define DUMP_INSTR()
1269 #endif
1270
1271 #ifdef __GNUC__
1272 #define USE_COMPUTED_GOTO 1
1273 #endif
1274 #if USE_COMPUTED_GOTO
1275 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
1276 #define MINT_IN_CASE(x) LAB_ ## x:
1277 #if DEBUG_INTERP
1278 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
1279 #else
1280 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
1281 #endif
1282 #define MINT_IN_DEFAULT mint_default:
1283 #else
1284 #define MINT_IN_SWITCH(op) switch (op)
1285 #define MINT_IN_CASE(x) case x:
1286 #define MINT_IN_BREAK break
1287 #define MINT_IN_DEFAULT default:
1288 #endif
1289
1290 /* 
1291  * Defining this causes register allocation errors in some versions of gcc:
1292  * error: unable to find a register to spill in class `SIREG'
1293  */
1294 /* #define MINT_USE_DEDICATED_IP_REG */
1295
1296 static void 
1297 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
1298 {
1299         MonoInvocation child_frame;
1300         GSList *finally_ips = NULL;
1301         const unsigned short *endfinally_ip = NULL;
1302 #if defined(__GNUC__) && defined (i386) && defined (MINT_USE_DEDICATED_IP_REG)
1303         register const unsigned short *ip asm ("%esi");
1304 #else
1305         register const unsigned short *ip;
1306 #endif
1307         register stackval *sp;
1308         RuntimeMethod *rtm;
1309 #if DEBUG_INTERP
1310         gint tracing = global_tracing;
1311         unsigned char *vtalloc;
1312 #endif
1313         int i32;
1314         unsigned char *vt_sp;
1315         char *locals;
1316         MonoObject *o = NULL;
1317         MonoClass *c;
1318 #if USE_COMPUTED_GOTO
1319         static void *in_labels[] = {
1320 #define OPDEF(a,b,c,d) \
1321         &&LAB_ ## a,
1322 #include "mintops.def"
1323         0 };
1324 #endif
1325
1326         frame->ex = NULL;
1327         frame->ex_handler = NULL;
1328         frame->ip = NULL;
1329         context->current_frame = frame;
1330
1331         DEBUG_ENTER ();
1332
1333         if (!frame->runtime_method->transformed) {
1334                 context->managed_code = 0;
1335                 frame->ex = mono_interp_transform_method (frame->runtime_method, context);
1336                 context->managed_code = 1;
1337                 if (frame->ex) {
1338                         rtm = NULL;
1339                         ip = NULL;
1340                         goto exit_frame;
1341                 }
1342         }
1343
1344         rtm = frame->runtime_method;
1345         frame->args = alloca (rtm->alloca_size);
1346         sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
1347 #if DEBUG_INTERP
1348         if (tracing > 1)
1349                 memset(sp, 0, rtm->stack_size);
1350 #endif
1351         vt_sp = (char *)sp + rtm->stack_size;
1352 #if DEBUG_INTERP
1353         vtalloc = vt_sp;
1354 #endif
1355         locals = vt_sp + rtm->vt_stack_size;
1356
1357         child_frame.parent = frame;
1358
1359         /* ready to go */
1360         ip = rtm->code;
1361
1362         /*
1363          * using while (ip < end) may result in a 15% performance drop, 
1364          * but it may be useful for debug
1365          */
1366         while (1) {
1367         main_loop:
1368                 /* g_assert (sp >= frame->stack); */
1369                 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
1370                 DUMP_INSTR();
1371                 MINT_IN_SWITCH (*ip) {
1372                 MINT_IN_CASE(MINT_INITLOCALS)
1373                         memset (locals, 0, rtm->locals_size);
1374                         ++ip;
1375                         MINT_IN_BREAK;
1376                 MINT_IN_CASE(MINT_NOP)
1377                         ++ip;
1378                         MINT_IN_BREAK;
1379                 MINT_IN_CASE(MINT_BREAK)
1380                         ++ip;
1381                         G_BREAKPOINT (); /* this is not portable... */
1382                         MINT_IN_BREAK;
1383                 MINT_IN_CASE(MINT_LDNULL) 
1384                         sp->data.p = NULL;
1385                         ++ip;
1386                         ++sp;
1387                         MINT_IN_BREAK;
1388                 MINT_IN_CASE(MINT_VTRESULT) {
1389                         int ret_size = * (guint16 *)(ip + 1);
1390                         char *ret_vt_sp = vt_sp;
1391                         vt_sp -= READ32(ip + 2);
1392                         if (ret_size > 0) {
1393                                 memmove (vt_sp, ret_vt_sp, ret_size);
1394                                 vt_sp += (ret_size + 7) & ~7;
1395                         }
1396                         ip += 4;
1397                         MINT_IN_BREAK;
1398                 }
1399 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
1400                 MINT_IN_CASE(MINT_LDC_I4_M1)
1401                         LDC(-1);
1402                         MINT_IN_BREAK;
1403                 MINT_IN_CASE(MINT_LDC_I4_0)
1404                         LDC(0);
1405                         MINT_IN_BREAK;
1406                 MINT_IN_CASE(MINT_LDC_I4_1)
1407                         LDC(1);
1408                         MINT_IN_BREAK;
1409                 MINT_IN_CASE(MINT_LDC_I4_2)
1410                         LDC(2);
1411                         MINT_IN_BREAK;
1412                 MINT_IN_CASE(MINT_LDC_I4_3)
1413                         LDC(3);
1414                         MINT_IN_BREAK;
1415                 MINT_IN_CASE(MINT_LDC_I4_4)
1416                         LDC(4);
1417                         MINT_IN_BREAK;
1418                 MINT_IN_CASE(MINT_LDC_I4_5)
1419                         LDC(5);
1420                         MINT_IN_BREAK;
1421                 MINT_IN_CASE(MINT_LDC_I4_6)
1422                         LDC(6);
1423                         MINT_IN_BREAK;
1424                 MINT_IN_CASE(MINT_LDC_I4_7)
1425                         LDC(7);
1426                         MINT_IN_BREAK;
1427                 MINT_IN_CASE(MINT_LDC_I4_8)
1428                         LDC(8);
1429                         MINT_IN_BREAK;
1430                 MINT_IN_CASE(MINT_LDC_I4_S) 
1431                         sp->data.i = *(const short *)(ip + 1);
1432                         ip += 2;
1433                         ++sp;
1434                         MINT_IN_BREAK;
1435                 MINT_IN_CASE(MINT_LDC_I4)
1436                         ++ip;
1437                         sp->data.i = READ32 (ip);
1438                         ip += 2;
1439                         ++sp;
1440                         MINT_IN_BREAK;
1441                 MINT_IN_CASE(MINT_LDC_I8)
1442                         ++ip;
1443                         sp->data.l = READ64 (ip);
1444                         ip += 4;
1445                         ++sp;
1446                         MINT_IN_BREAK;
1447                 MINT_IN_CASE(MINT_LDC_R4) {
1448                         guint32 val;
1449                         ++ip;
1450                         val = READ32(ip);
1451                         sp->data.f = * (float *)&val;
1452                         ip += 2;
1453                         ++sp;
1454                         MINT_IN_BREAK;
1455                 }
1456                 MINT_IN_CASE(MINT_LDC_R8) 
1457                         sp->data.l = READ64 (ip + 1); /* note union usage */
1458                         ip += 5;
1459                         ++sp;
1460                         MINT_IN_BREAK;
1461                 MINT_IN_CASE(MINT_DUP) 
1462                         sp [0] = sp[-1];
1463                         ++sp;
1464                         ++ip; 
1465                         MINT_IN_BREAK;
1466                 MINT_IN_CASE(MINT_DUP_VT)
1467                         i32 = READ32 (ip + 1);
1468                         sp->data.p = vt_sp;
1469                         memcpy(sp->data.p, sp [-1].data.p, i32);
1470                         vt_sp += (i32 + 7) & ~7;
1471                         ++sp;
1472                         ip += 3;
1473                         MINT_IN_BREAK;
1474                 MINT_IN_CASE(MINT_POP)
1475                         ++ip;
1476                         --sp;
1477                         MINT_IN_BREAK;
1478                 MINT_IN_CASE(MINT_JMP) {
1479                         RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
1480                         if (!new_method->transformed) {
1481                                 frame->ip = ip;
1482                                 frame->ex = mono_interp_transform_method (new_method, context);
1483                                 if (frame->ex)
1484                                         goto exit_frame;
1485                         }
1486                         ip += 2;
1487                         if (new_method->alloca_size > rtm->alloca_size)
1488                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
1489                         rtm = frame->runtime_method = new_method;
1490                         vt_sp = (char *)sp + rtm->stack_size;
1491 #if DEBUG_INTERP
1492                         vtalloc = vt_sp;
1493 #endif
1494                         locals = vt_sp + rtm->vt_stack_size;
1495                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
1496                         MINT_IN_BREAK;
1497                 }
1498                 MINT_IN_CASE(MINT_CALLI) {
1499                         MonoMethodSignature *csignature;
1500                         stackval *endsp = sp;
1501
1502                         frame->ip = ip;
1503                         
1504                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1505                         ip += 2;
1506                         --sp;
1507                         --endsp;
1508                         child_frame.runtime_method = sp->data.p;
1509
1510                         sp->data.p = vt_sp;
1511                         child_frame.retval = sp;
1512                         /* decrement by the actual number of args */
1513                         sp -= csignature->param_count;
1514                         child_frame.stack_args = sp;
1515                         if (csignature->hasthis) {
1516                                 --sp;
1517                                 child_frame.obj = sp->data.p;
1518                         } else {
1519                                 child_frame.obj = NULL;
1520                         }
1521                         if (csignature->hasthis &&
1522                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1523                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1524                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1525                         } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
1526                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1527                                                                 mono_marshal_get_native_wrapper (child_frame.runtime_method->method));
1528
1529                         ves_exec_method_with_context (&child_frame, context);
1530
1531                         context->current_frame = frame;
1532
1533                         if (child_frame.ex) {
1534                                 /*
1535                                  * An exception occurred, need to run finally, fault and catch handlers..
1536                                  */
1537                                 frame->ex = child_frame.ex;
1538                                 goto handle_finally;
1539                         }
1540
1541                         /* need to handle typedbyref ... */
1542                         if (csignature->ret->type != MONO_TYPE_VOID) {
1543                                 *sp = *endsp;
1544                                 sp++;
1545                         }
1546                         MINT_IN_BREAK;
1547                 }
1548                 MINT_IN_CASE(MINT_CALLI_NAT) {
1549                         MonoMethodSignature *csignature;
1550                         stackval *endsp = sp;
1551                         unsigned char *code = NULL;
1552
1553                         frame->ip = ip;
1554                         
1555                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1556                         ip += 2;
1557                         --sp;
1558                         --endsp;
1559                         code = sp->data.p;
1560                         child_frame.runtime_method = NULL;
1561
1562                         sp->data.p = vt_sp;
1563                         child_frame.retval = sp;
1564                         /* decrement by the actual number of args */
1565                         sp -= csignature->param_count;
1566                         child_frame.stack_args = sp;
1567                         if (csignature->hasthis) {
1568                                 --sp;
1569                                 child_frame.obj = sp->data.p;
1570                         } else {
1571                                 child_frame.obj = NULL;
1572                         }
1573                         ves_pinvoke_method (&child_frame, csignature, (MonoFunc) code, FALSE, context);
1574
1575                         context->current_frame = frame;
1576
1577                         if (child_frame.ex) {
1578                                 /*
1579                                  * An exception occurred, need to run finally, fault and catch handlers..
1580                                  */
1581                                 frame->ex = child_frame.ex;
1582                                 if (context->search_for_handler) {
1583                                         context->search_for_handler = 0;
1584                                         goto handle_exception;
1585                                 }
1586                                 goto handle_finally;
1587                         }
1588
1589                         /* need to handle typedbyref ... */
1590                         if (csignature->ret->type != MONO_TYPE_VOID) {
1591                                 *sp = *endsp;
1592                                 sp++;
1593                         }
1594                         MINT_IN_BREAK;
1595                 }
1596                 MINT_IN_CASE(MINT_CALL) {
1597                         stackval *endsp = sp;
1598
1599                         frame->ip = ip;
1600                         
1601                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1602                         ip += 2;
1603                         sp->data.p = vt_sp;
1604                         child_frame.retval = sp;
1605                         /* decrement by the actual number of args */
1606                         sp -= child_frame.runtime_method->param_count;
1607                         child_frame.stack_args = sp;
1608                         if (child_frame.runtime_method->hasthis) {
1609                                 --sp;
1610                                 child_frame.obj = sp->data.p;
1611                         } else {
1612                                 child_frame.obj = NULL;
1613                         }
1614                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
1615                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1616                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1617                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1618                         }
1619                         ves_exec_method_with_context (&child_frame, context);
1620
1621                         context->current_frame = frame;
1622
1623                         if (child_frame.ex) {
1624                                 /*
1625                                  * An exception occurred, need to run finally, fault and catch handlers..
1626                                  */
1627                                 frame->ex = child_frame.ex;
1628                                 goto handle_finally;
1629                         }
1630
1631                         /* need to handle typedbyref ... */
1632                         *sp = *endsp;
1633                         sp++;
1634                         MINT_IN_BREAK;
1635                 }
1636                 MINT_IN_CASE(MINT_VCALL) {
1637                         frame->ip = ip;
1638                         
1639                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1640                         ip += 2;
1641
1642                         sp->data.p = vt_sp;
1643                         child_frame.retval = sp;
1644                         /* decrement by the actual number of args */
1645                         sp -= child_frame.runtime_method->param_count;
1646                         child_frame.stack_args = sp;
1647                         if (child_frame.runtime_method->hasthis) {
1648                                 --sp;
1649                                 child_frame.obj = sp->data.p;
1650                         } else {
1651                                 child_frame.obj = NULL;
1652                         }
1653
1654                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
1655                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1656                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1657                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1658                         }
1659
1660                         ves_exec_method_with_context (&child_frame, context);
1661
1662                         context->current_frame = frame;
1663
1664                         if (child_frame.ex) {
1665                                 /*
1666                                  * An exception occurred, need to run finally, fault and catch handlers..
1667                                  */
1668                                 frame->ex = child_frame.ex;
1669                                 goto handle_finally;
1670                         }
1671                         MINT_IN_BREAK;
1672                 }
1673                 MINT_IN_CASE(MINT_CALLVIRT) {
1674                         stackval *endsp = sp;
1675                         MonoObject *this_arg;
1676                         guint32 token;
1677
1678                         frame->ip = ip;
1679                         
1680                         token = * (unsigned short *)(ip + 1);
1681                         ip += 2;
1682                         child_frame.runtime_method = rtm->data_items [token];
1683                         sp->data.p = vt_sp;
1684                         child_frame.retval = sp;
1685
1686                         /* decrement by the actual number of args */
1687                         sp -= child_frame.runtime_method->param_count;
1688                         child_frame.stack_args = sp;
1689                         --sp;
1690                         child_frame.obj = this_arg = sp->data.p;
1691                         if (!this_arg)
1692                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
1693                         child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
1694
1695                         if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
1696                                 child_frame.obj = (char *)this_arg + sizeof(MonoObject);
1697                         }
1698
1699                         ves_exec_method_with_context (&child_frame, context);
1700
1701                         context->current_frame = frame;
1702
1703                         if (child_frame.ex) {
1704                                 /*
1705                                  * An exception occurred, need to run finally, fault and catch handlers..
1706                                  */
1707                                 frame->ex = child_frame.ex;
1708                                 if (context->search_for_handler) {
1709                                         context->search_for_handler = 0;
1710                                         goto handle_exception;
1711                                 }
1712                                 goto handle_finally;
1713                         }
1714
1715                         /* need to handle typedbyref ... */
1716                         *sp = *endsp;
1717                         sp++;
1718                         MINT_IN_BREAK;
1719                 }
1720                 MINT_IN_CASE(MINT_VCALLVIRT) {
1721                         MonoObject *this_arg;
1722                         guint32 token;
1723
1724                         frame->ip = ip;
1725                         
1726                         token = * (unsigned short *)(ip + 1);
1727                         ip += 2;
1728                         child_frame.runtime_method = rtm->data_items [token];
1729                         sp->data.p = vt_sp;
1730                         child_frame.retval = sp;
1731
1732                         /* decrement by the actual number of args */
1733                         sp -= child_frame.runtime_method->param_count;
1734                         child_frame.stack_args = sp;
1735                         --sp;
1736                         child_frame.obj = this_arg = sp->data.p;
1737                         if (!this_arg)
1738                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
1739                         child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
1740
1741                         if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
1742                                 child_frame.obj = (char *)this_arg + sizeof(MonoObject);
1743                         }
1744
1745                         ves_exec_method_with_context (&child_frame, context);
1746
1747                         context->current_frame = frame;
1748
1749                         if (child_frame.ex) {
1750                                 /*
1751                                  * An exception occurred, need to run finally, fault and catch handlers..
1752                                  */
1753                                 frame->ex = child_frame.ex;
1754                                 if (context->search_for_handler) {
1755                                         context->search_for_handler = 0;
1756                                         goto handle_exception;
1757                                 }
1758                                 goto handle_finally;
1759                         }
1760                         MINT_IN_BREAK;
1761                 }
1762                 MINT_IN_CASE(MINT_CALLINT)
1763                         ves_pinvoke_method (frame, frame->runtime_method->method->signature, frame->runtime_method->method->addr, 
1764                                     frame->runtime_method->method->string_ctor, context);
1765                         if (frame->ex) {
1766                                 rtm = NULL;
1767                                 goto handle_exception;
1768                         }
1769                         goto exit_frame;
1770                 MINT_IN_CASE(MINT_CALLRUN)
1771                         ves_runtime_method (frame, context);
1772                         if (frame->ex) {
1773                                 rtm = NULL;
1774                                 goto handle_exception;
1775                         }
1776                         goto exit_frame;
1777                 MINT_IN_CASE(MINT_RET)
1778                         --sp;
1779                         *frame->retval = *sp;
1780                         if (sp > frame->stack)
1781                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
1782                         goto exit_frame;
1783                 MINT_IN_CASE(MINT_RET_VOID)
1784                         if (sp > frame->stack)
1785                                 g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
1786                         goto exit_frame;
1787                 MINT_IN_CASE(MINT_RET_VT)
1788                         i32 = READ32(ip + 1);
1789                         --sp;
1790                         memcpy(frame->retval->data.p, sp->data.p, i32);
1791                         if (sp > frame->stack)
1792                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
1793                         goto exit_frame;
1794                 MINT_IN_CASE(MINT_BR_S)
1795                         ip += (short) *(ip + 1);
1796                         MINT_IN_BREAK;
1797                 MINT_IN_CASE(MINT_BR)
1798                         ip += (gint32) READ32(ip + 1);
1799                         MINT_IN_BREAK;
1800 #define ZEROP_S(datamem, op) \
1801         --sp; \
1802         if (sp->data.datamem op 0) \
1803                 ip += * (gint16 *)(ip + 1); \
1804         else \
1805                 ip += 2;
1806
1807 #define ZEROP(datamem, op) \
1808         --sp; \
1809         if (sp->data.datamem op 0) \
1810                 ip += READ32(ip + 1); \
1811         else \
1812                 ip += 3;
1813
1814                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
1815                         ZEROP_S(i, ==);
1816                         MINT_IN_BREAK;
1817                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
1818                         ZEROP_S(l, ==);
1819                         MINT_IN_BREAK;
1820                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
1821                         ZEROP_S(f, ==);
1822                         MINT_IN_BREAK;
1823                 MINT_IN_CASE(MINT_BRFALSE_I4)
1824                         ZEROP(i, ==);
1825                         MINT_IN_BREAK;
1826                 MINT_IN_CASE(MINT_BRFALSE_I8)
1827                         ZEROP(l, ==);
1828                         MINT_IN_BREAK;
1829                 MINT_IN_CASE(MINT_BRFALSE_R8)
1830                         ZEROP_S(f, ==);
1831                         MINT_IN_BREAK;
1832                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
1833                         ZEROP_S(i, !=);
1834                         MINT_IN_BREAK;
1835                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
1836                         ZEROP_S(l, !=);
1837                         MINT_IN_BREAK;
1838                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
1839                         ZEROP_S(f, !=);
1840                         MINT_IN_BREAK;
1841                 MINT_IN_CASE(MINT_BRTRUE_I4)
1842                         ZEROP(i, !=);
1843                         MINT_IN_BREAK;
1844                 MINT_IN_CASE(MINT_BRTRUE_I8)
1845                         ZEROP(l, !=);
1846                         MINT_IN_BREAK;
1847                 MINT_IN_CASE(MINT_BRTRUE_R8)
1848                         ZEROP(f, !=);
1849                         MINT_IN_BREAK;
1850 #define CONDBR_S(cond) \
1851         sp -= 2; \
1852         if (cond) \
1853                 ip += * (gint16 *)(ip + 1); \
1854         else \
1855                 ip += 2;
1856 #define BRELOP_S(datamem, op) \
1857         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
1858
1859 #define CONDBR(cond) \
1860         sp -= 2; \
1861         if (cond) \
1862                 ip += READ32(ip + 1); \
1863         else \
1864                 ip += 3;
1865
1866 #define BRELOP(datamem, op) \
1867         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
1868
1869                 MINT_IN_CASE(MINT_BEQ_I4_S)
1870                         BRELOP_S(i, ==)
1871                         MINT_IN_BREAK;
1872                 MINT_IN_CASE(MINT_BEQ_I8_S)
1873                         BRELOP_S(l, ==)
1874                         MINT_IN_BREAK;
1875                 MINT_IN_CASE(MINT_BEQ_R8_S)
1876                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
1877                         MINT_IN_BREAK;
1878                 MINT_IN_CASE(MINT_BEQ_I4)
1879                         BRELOP(i, ==)
1880                         MINT_IN_BREAK;
1881                 MINT_IN_CASE(MINT_BEQ_I8)
1882                         BRELOP(l, ==)
1883                         MINT_IN_BREAK;
1884                 MINT_IN_CASE(MINT_BEQ_R8)
1885                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
1886                         MINT_IN_BREAK;
1887                 MINT_IN_CASE(MINT_BGE_I4_S)
1888                         BRELOP_S(i, >=)
1889                         MINT_IN_BREAK;
1890                 MINT_IN_CASE(MINT_BGE_I8_S)
1891                         BRELOP_S(l, >=)
1892                         MINT_IN_BREAK;
1893                 MINT_IN_CASE(MINT_BGE_R8_S)
1894                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
1895                         MINT_IN_BREAK;
1896                 MINT_IN_CASE(MINT_BGE_I4)
1897                         BRELOP(i, >=)
1898                         MINT_IN_BREAK;
1899                 MINT_IN_CASE(MINT_BGE_I8)
1900                         BRELOP(l, >=)
1901                         MINT_IN_BREAK;
1902                 MINT_IN_CASE(MINT_BGE_R8)
1903                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
1904                         MINT_IN_BREAK;
1905                 MINT_IN_CASE(MINT_BGT_I4_S)
1906                         BRELOP_S(i, >)
1907                         MINT_IN_BREAK;
1908                 MINT_IN_CASE(MINT_BGT_I8_S)
1909                         BRELOP_S(l, >)
1910                         MINT_IN_BREAK;
1911                 MINT_IN_CASE(MINT_BGT_R8_S)
1912                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
1913                         MINT_IN_BREAK;
1914                 MINT_IN_CASE(MINT_BGT_I4)
1915                         BRELOP(i, >)
1916                         MINT_IN_BREAK;
1917                 MINT_IN_CASE(MINT_BGT_I8)
1918                         BRELOP(l, >)
1919                         MINT_IN_BREAK;
1920                 MINT_IN_CASE(MINT_BGT_R8)
1921                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
1922                         MINT_IN_BREAK;
1923                 MINT_IN_CASE(MINT_BLT_I4_S)
1924                         BRELOP_S(i, <)
1925                         MINT_IN_BREAK;
1926                 MINT_IN_CASE(MINT_BLT_I8_S)
1927                         BRELOP_S(l, <)
1928                         MINT_IN_BREAK;
1929                 MINT_IN_CASE(MINT_BLT_R8_S)
1930                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
1931                         MINT_IN_BREAK;
1932                 MINT_IN_CASE(MINT_BLT_I4)
1933                         BRELOP(i, <)
1934                         MINT_IN_BREAK;
1935                 MINT_IN_CASE(MINT_BLT_I8)
1936                         BRELOP(l, <)
1937                         MINT_IN_BREAK;
1938                 MINT_IN_CASE(MINT_BLT_R8)
1939                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
1940                         MINT_IN_BREAK;
1941                 MINT_IN_CASE(MINT_BLE_I4_S)
1942                         BRELOP_S(i, <=)
1943                         MINT_IN_BREAK;
1944                 MINT_IN_CASE(MINT_BLE_I8_S)
1945                         BRELOP_S(l, <=)
1946                         MINT_IN_BREAK;
1947                 MINT_IN_CASE(MINT_BLE_R8_S)
1948                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
1949                         MINT_IN_BREAK;
1950                 MINT_IN_CASE(MINT_BLE_I4)
1951                         BRELOP(i, <=)
1952                         MINT_IN_BREAK;
1953                 MINT_IN_CASE(MINT_BLE_I8)
1954                         BRELOP(l, <=)
1955                         MINT_IN_BREAK;
1956                 MINT_IN_CASE(MINT_BLE_R8)
1957                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
1958                         MINT_IN_BREAK;
1959                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
1960                         BRELOP_S(i, !=)
1961                         MINT_IN_BREAK;
1962                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
1963                         BRELOP_S(l, !=)
1964                         MINT_IN_BREAK;
1965                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
1966                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
1967                         MINT_IN_BREAK;
1968                 MINT_IN_CASE(MINT_BNE_UN_I4)
1969                         BRELOP(i, !=)
1970                         MINT_IN_BREAK;
1971                 MINT_IN_CASE(MINT_BNE_UN_I8)
1972                         BRELOP(l, !=)
1973                         MINT_IN_BREAK;
1974                 MINT_IN_CASE(MINT_BNE_UN_R8)
1975                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
1976                         MINT_IN_BREAK;
1977
1978 #define BRELOP_S_CAST(datamem, op, type) \
1979         sp -= 2; \
1980         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
1981                 ip += * (gint16 *)(ip + 1); \
1982         else \
1983                 ip += 2;
1984
1985 #define BRELOP_CAST(datamem, op, type) \
1986         sp -= 2; \
1987         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
1988                 ip += READ32(ip + 1); \
1989         else \
1990                 ip += 3;
1991
1992                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
1993                         BRELOP_S_CAST(i, >=, guint32);
1994                         MINT_IN_BREAK;
1995                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
1996                         BRELOP_S_CAST(l, >=, guint64);
1997                         MINT_IN_BREAK;
1998                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
1999                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2000                         MINT_IN_BREAK;
2001                 MINT_IN_CASE(MINT_BGE_UN_I4)
2002                         BRELOP_CAST(i, >=, guint32);
2003                         MINT_IN_BREAK;
2004                 MINT_IN_CASE(MINT_BGE_UN_I8)
2005                         BRELOP_CAST(l, >=, guint64);
2006                         MINT_IN_BREAK;
2007                 MINT_IN_CASE(MINT_BGE_UN_R8)
2008                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2009                         MINT_IN_BREAK;
2010                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
2011                         BRELOP_S_CAST(i, >, guint32);
2012                         MINT_IN_BREAK;
2013                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
2014                         BRELOP_S_CAST(l, >, guint64);
2015                         MINT_IN_BREAK;
2016                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
2017                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2018                         MINT_IN_BREAK;
2019                 MINT_IN_CASE(MINT_BGT_UN_I4)
2020                         BRELOP_CAST(i, >, guint32);
2021                         MINT_IN_BREAK;
2022                 MINT_IN_CASE(MINT_BGT_UN_I8)
2023                         BRELOP_CAST(l, >, guint64);
2024                         MINT_IN_BREAK;
2025                 MINT_IN_CASE(MINT_BGT_UN_R8)
2026                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2027                         MINT_IN_BREAK;
2028                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
2029                         BRELOP_S_CAST(i, <=, guint32);
2030                         MINT_IN_BREAK;
2031                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
2032                         BRELOP_S_CAST(l, <=, guint64);
2033                         MINT_IN_BREAK;
2034                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
2035                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2036                         MINT_IN_BREAK;
2037                 MINT_IN_CASE(MINT_BLE_UN_I4)
2038                         BRELOP_CAST(i, <=, guint32);
2039                         MINT_IN_BREAK;
2040                 MINT_IN_CASE(MINT_BLE_UN_I8)
2041                         BRELOP_CAST(l, <=, guint64);
2042                         MINT_IN_BREAK;
2043                 MINT_IN_CASE(MINT_BLE_UN_R8)
2044                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2045                         MINT_IN_BREAK;
2046                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
2047                         BRELOP_S_CAST(i, <, guint32);
2048                         MINT_IN_BREAK;
2049                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
2050                         BRELOP_S_CAST(l, <, guint64);
2051                         MINT_IN_BREAK;
2052                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
2053                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2054                         MINT_IN_BREAK;
2055                 MINT_IN_CASE(MINT_BLT_UN_I4)
2056                         BRELOP_CAST(i, <, guint32);
2057                         MINT_IN_BREAK;
2058                 MINT_IN_CASE(MINT_BLT_UN_I8)
2059                         BRELOP_CAST(l, <, guint64);
2060                         MINT_IN_BREAK;
2061                 MINT_IN_CASE(MINT_BLT_UN_R8)
2062                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2063                         MINT_IN_BREAK;
2064                 MINT_IN_CASE(MINT_SWITCH) {
2065                         guint32 n;
2066                         const unsigned short *st;
2067                         ++ip;
2068                         n = READ32 (ip);
2069                         ip += 2;
2070                         st = ip + 2 * n;
2071                         --sp;
2072                         if ((guint32)sp->data.i < n) {
2073                                 gint offset;
2074                                 ip += 2 * (guint32)sp->data.i;
2075                                 offset = READ32 (ip);
2076                                 ip = st + offset;
2077                         } else {
2078                                 ip = st;
2079                         }
2080                         MINT_IN_BREAK;
2081                 }
2082                 MINT_IN_CASE(MINT_LDIND_I1)
2083                         ++ip;
2084                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
2085                         MINT_IN_BREAK;
2086                 MINT_IN_CASE(MINT_LDIND_U1)
2087                         ++ip;
2088                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
2089                         MINT_IN_BREAK;
2090                 MINT_IN_CASE(MINT_LDIND_I2)
2091                         ++ip;
2092                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
2093                         MINT_IN_BREAK;
2094                 MINT_IN_CASE(MINT_LDIND_U2)
2095                         ++ip;
2096                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
2097                         MINT_IN_BREAK;
2098                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
2099                 MINT_IN_CASE(MINT_LDIND_U4)
2100                         ++ip;
2101                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
2102                         MINT_IN_BREAK;
2103                 MINT_IN_CASE(MINT_LDIND_I8)
2104                         ++ip;
2105                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
2106                         MINT_IN_BREAK;
2107                 MINT_IN_CASE(MINT_LDIND_I)
2108                         ++ip;
2109                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2110                         MINT_IN_BREAK;
2111                 MINT_IN_CASE(MINT_LDIND_R4)
2112                         ++ip;
2113                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
2114                         MINT_IN_BREAK;
2115                 MINT_IN_CASE(MINT_LDIND_R8)
2116                         ++ip;
2117                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
2118                         MINT_IN_BREAK;
2119                 MINT_IN_CASE(MINT_LDIND_REF)
2120                         ++ip;
2121                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2122                         MINT_IN_BREAK;
2123                 MINT_IN_CASE(MINT_STIND_REF) 
2124                         ++ip;
2125                         sp -= 2;
2126                         * (gpointer *) sp->data.p = sp[1].data.p;
2127                         MINT_IN_BREAK;
2128                 MINT_IN_CASE(MINT_STIND_I1)
2129                         ++ip;
2130                         sp -= 2;
2131                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
2132                         MINT_IN_BREAK;
2133                 MINT_IN_CASE(MINT_STIND_I2)
2134                         ++ip;
2135                         sp -= 2;
2136                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
2137                         MINT_IN_BREAK;
2138                 MINT_IN_CASE(MINT_STIND_I4)
2139                         ++ip;
2140                         sp -= 2;
2141                         * (gint32 *) sp->data.p = sp[1].data.i;
2142                         MINT_IN_BREAK;
2143                 MINT_IN_CASE(MINT_STIND_I)
2144                         ++ip;
2145                         sp -= 2;
2146                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
2147                         MINT_IN_BREAK;
2148                 MINT_IN_CASE(MINT_STIND_I8)
2149                         ++ip;
2150                         sp -= 2;
2151                         * (gint64 *) sp->data.p = sp[1].data.l;
2152                         MINT_IN_BREAK;
2153                 MINT_IN_CASE(MINT_STIND_R4)
2154                         ++ip;
2155                         sp -= 2;
2156                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
2157                         MINT_IN_BREAK;
2158                 MINT_IN_CASE(MINT_STIND_R8)
2159                         ++ip;
2160                         sp -= 2;
2161                         * (double *) sp->data.p = sp[1].data.f;
2162                         MINT_IN_BREAK;
2163 #define BINOP(datamem, op) \
2164         --sp; \
2165         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
2166         ++ip;
2167                 MINT_IN_CASE(MINT_ADD_I4)
2168                         BINOP(i, +);
2169                         MINT_IN_BREAK;
2170                 MINT_IN_CASE(MINT_ADD_I8)
2171                         BINOP(l, +);
2172                         MINT_IN_BREAK;
2173                 MINT_IN_CASE(MINT_ADD_R8)
2174                         BINOP(f, +);
2175                         MINT_IN_BREAK;
2176                 MINT_IN_CASE(MINT_ADD1_I4)
2177                         ++sp [-1].data.i;
2178                         ++ip;
2179                         MINT_IN_BREAK;
2180                 MINT_IN_CASE(MINT_SUB_I4)
2181                         BINOP(i, -);
2182                         MINT_IN_BREAK;
2183                 MINT_IN_CASE(MINT_SUB_I8)
2184                         BINOP(l, -);
2185                         MINT_IN_BREAK;
2186                 MINT_IN_CASE(MINT_SUB_R8)
2187                         BINOP(f, -);
2188                         MINT_IN_BREAK;
2189                 MINT_IN_CASE(MINT_SUB1_I4)
2190                         --sp [-1].data.i;
2191                         ++ip;
2192                         MINT_IN_BREAK;
2193                 MINT_IN_CASE(MINT_MUL_I4)
2194                         BINOP(i, *);
2195                         MINT_IN_BREAK;
2196                 MINT_IN_CASE(MINT_MUL_I8)
2197                         BINOP(l, *);
2198                         MINT_IN_BREAK;
2199                 MINT_IN_CASE(MINT_MUL_R8)
2200                         BINOP(f, *);
2201                         MINT_IN_BREAK;
2202                 MINT_IN_CASE(MINT_DIV_I4)
2203                         if (sp [-1].data.i == 0)
2204                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2205                         BINOP(i, /);
2206                         MINT_IN_BREAK;
2207                 MINT_IN_CASE(MINT_DIV_I8)
2208                         if (sp [-1].data.l == 0)
2209                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2210                         BINOP(l, /);
2211                         MINT_IN_BREAK;
2212                 MINT_IN_CASE(MINT_DIV_R8)
2213                         BINOP(f, /);
2214                         MINT_IN_BREAK;
2215
2216 #define BINOP_CAST(datamem, op, type) \
2217         --sp; \
2218         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
2219         ++ip;
2220                 MINT_IN_CASE(MINT_DIV_UN_I4)
2221                         if (sp [-1].data.i == 0)
2222                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2223                         BINOP_CAST(i, /, guint32);
2224                         MINT_IN_BREAK;
2225                 MINT_IN_CASE(MINT_DIV_UN_I8)
2226                         if (sp [-1].data.l == 0)
2227                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2228                         BINOP_CAST(l, /, guint64);
2229                         MINT_IN_BREAK;
2230                 MINT_IN_CASE(MINT_REM_I4)
2231                         if (sp [-1].data.i == 0)
2232                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2233                         BINOP(i, %);
2234                         MINT_IN_BREAK;
2235                 MINT_IN_CASE(MINT_REM_I8)
2236                         if (sp [-1].data.l == 0)
2237                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2238                         BINOP(l, %);
2239                         MINT_IN_BREAK;
2240                 MINT_IN_CASE(MINT_REM_R8)
2241                         /* FIXME: what do we actually do here? */
2242                         --sp;
2243                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
2244                         ++ip;
2245                         MINT_IN_BREAK;
2246                 MINT_IN_CASE(MINT_REM_UN_I4)
2247                         if (sp [-1].data.i == 0)
2248                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2249                         BINOP_CAST(i, %, guint32);
2250                         MINT_IN_BREAK;
2251                 MINT_IN_CASE(MINT_REM_UN_I8)
2252                         if (sp [-1].data.l == 0)
2253                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2254                         BINOP_CAST(l, %, guint64);
2255                         MINT_IN_BREAK;
2256                 MINT_IN_CASE(MINT_AND_I4)
2257                         BINOP(i, &);
2258                         MINT_IN_BREAK;
2259                 MINT_IN_CASE(MINT_AND_I8)
2260                         BINOP(l, &);
2261                         MINT_IN_BREAK;
2262                 MINT_IN_CASE(MINT_OR_I4)
2263                         BINOP(i, |);
2264                         MINT_IN_BREAK;
2265                 MINT_IN_CASE(MINT_OR_I8)
2266                         BINOP(l, |);
2267                         MINT_IN_BREAK;
2268                 MINT_IN_CASE(MINT_XOR_I4)
2269                         BINOP(i, ^);
2270                         MINT_IN_BREAK;
2271                 MINT_IN_CASE(MINT_XOR_I8)
2272                         BINOP(l, ^);
2273                         MINT_IN_BREAK;
2274
2275 #define SHIFTOP(datamem, op) \
2276         --sp; \
2277         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
2278         ++ip;
2279
2280                 MINT_IN_CASE(MINT_SHL_I4)
2281                         SHIFTOP(i, <<);
2282                         MINT_IN_BREAK;
2283                 MINT_IN_CASE(MINT_SHL_I8)
2284                         SHIFTOP(l, <<);
2285                         MINT_IN_BREAK;
2286                 MINT_IN_CASE(MINT_SHR_I4)
2287                         SHIFTOP(i, >>);
2288                         MINT_IN_BREAK;
2289                 MINT_IN_CASE(MINT_SHR_I8)
2290                         SHIFTOP(l, >>);
2291                         MINT_IN_BREAK;
2292                 MINT_IN_CASE(MINT_SHR_UN_I4)
2293                         --sp;
2294                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
2295                         ++ip;
2296                         MINT_IN_BREAK;
2297                 MINT_IN_CASE(MINT_SHR_UN_I8)
2298                         --sp;
2299                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
2300                         ++ip;
2301                         MINT_IN_BREAK;
2302                 MINT_IN_CASE(MINT_NEG_I4)
2303                         sp [-1].data.i = - sp [-1].data.i;
2304                         ++ip;
2305                         MINT_IN_BREAK;
2306                 MINT_IN_CASE(MINT_NEG_I8)
2307                         sp [-1].data.l = - sp [-1].data.l;
2308                         ++ip;
2309                         MINT_IN_BREAK;
2310                 MINT_IN_CASE(MINT_NEG_R8)
2311                         sp [-1].data.f = - sp [-1].data.f;
2312                         ++ip;
2313                         MINT_IN_BREAK;
2314                 MINT_IN_CASE(MINT_NOT_I4)
2315                         sp [-1].data.i = ~ sp [-1].data.i;
2316                         ++ip;
2317                         MINT_IN_BREAK;
2318                 MINT_IN_CASE(MINT_NOT_I8)
2319                         sp [-1].data.l = ~ sp [-1].data.l;
2320                         ++ip;
2321                         MINT_IN_BREAK;
2322                 MINT_IN_CASE(MINT_CONV_I1_I4)
2323                         sp [-1].data.i = (gint8)sp [-1].data.i;
2324                         ++ip;
2325                         MINT_IN_BREAK;
2326                 MINT_IN_CASE(MINT_CONV_I1_I8)
2327                         sp [-1].data.i = (gint8)sp [-1].data.l;
2328                         ++ip;
2329                         MINT_IN_BREAK;
2330                 MINT_IN_CASE(MINT_CONV_I1_R8)
2331                         sp [-1].data.i = (gint8)sp [-1].data.f;
2332                         ++ip;
2333                         MINT_IN_BREAK;
2334                 MINT_IN_CASE(MINT_CONV_U1_I4)
2335                         sp [-1].data.i = (guint8)sp [-1].data.i;
2336                         ++ip;
2337                         MINT_IN_BREAK;
2338                 MINT_IN_CASE(MINT_CONV_U1_I8)
2339                         sp [-1].data.i = (guint8)sp [-1].data.l;
2340                         ++ip;
2341                         MINT_IN_BREAK;
2342                 MINT_IN_CASE(MINT_CONV_U1_R8)
2343                         sp [-1].data.i = (guint8)sp [-1].data.f;
2344                         ++ip;
2345                         MINT_IN_BREAK;
2346                 MINT_IN_CASE(MINT_CONV_I2_I4)
2347                         sp [-1].data.i = (gint16)sp [-1].data.i;
2348                         ++ip;
2349                         MINT_IN_BREAK;
2350                 MINT_IN_CASE(MINT_CONV_I2_I8)
2351                         sp [-1].data.i = (gint16)sp [-1].data.l;
2352                         ++ip;
2353                         MINT_IN_BREAK;
2354                 MINT_IN_CASE(MINT_CONV_I2_R8)
2355                         sp [-1].data.i = (gint16)sp [-1].data.f;
2356                         ++ip;
2357                         MINT_IN_BREAK;
2358                 MINT_IN_CASE(MINT_CONV_U2_I4)
2359                         sp [-1].data.i = (guint16)sp [-1].data.i;
2360                         ++ip;
2361                         MINT_IN_BREAK;
2362                 MINT_IN_CASE(MINT_CONV_U2_I8)
2363                         sp [-1].data.i = (guint16)sp [-1].data.l;
2364                         ++ip;
2365                         MINT_IN_BREAK;
2366                 MINT_IN_CASE(MINT_CONV_U2_R8)
2367                         sp [-1].data.i = (guint16)sp [-1].data.f;
2368                         ++ip;
2369                         MINT_IN_BREAK;
2370                 MINT_IN_CASE(MINT_CONV_I4_R8)
2371                         sp [-1].data.i = (gint32)sp [-1].data.f;
2372                         ++ip;
2373                         MINT_IN_BREAK;
2374                 MINT_IN_CASE(MINT_CONV_U4_I8)
2375                 MINT_IN_CASE(MINT_CONV_I4_I8)
2376                         sp [-1].data.i = (gint32)sp [-1].data.l;
2377                         ++ip;
2378                         MINT_IN_BREAK;
2379                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
2380                         sp [-2].data.i = (gint32)sp [-2].data.l;
2381                         ++ip;
2382                         MINT_IN_BREAK;
2383                 MINT_IN_CASE(MINT_CONV_U4_R8)
2384                         sp [-1].data.i = (guint32)sp [-1].data.f;
2385                         ++ip;
2386                         MINT_IN_BREAK;
2387                 MINT_IN_CASE(MINT_CONV_I8_I4)
2388                         sp [-1].data.l = sp [-1].data.i;
2389                         ++ip;
2390                         MINT_IN_BREAK;
2391                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
2392                         sp [-2].data.l = sp [-2].data.i;
2393                         ++ip;
2394                         MINT_IN_BREAK;
2395                 MINT_IN_CASE(MINT_CONV_I8_U4)
2396                         sp [-1].data.l = (guint32)sp [-1].data.i;
2397                         ++ip;
2398                         MINT_IN_BREAK;
2399                 MINT_IN_CASE(MINT_CONV_I8_R8)
2400                         sp [-1].data.l = (gint64)sp [-1].data.f;
2401                         ++ip;
2402                         MINT_IN_BREAK;
2403                 MINT_IN_CASE(MINT_CONV_R4_I4)
2404                         sp [-1].data.f = (float)sp [-1].data.i;
2405                         ++ip;
2406                         MINT_IN_BREAK;
2407                 MINT_IN_CASE(MINT_CONV_R4_I8)
2408                         sp [-1].data.f = (float)sp [-1].data.l;
2409                         ++ip;
2410                         MINT_IN_BREAK;
2411                 MINT_IN_CASE(MINT_CONV_R4_R8)
2412                         sp [-1].data.f = (float)sp [-1].data.f;
2413                         ++ip;
2414                         MINT_IN_BREAK;
2415                 MINT_IN_CASE(MINT_CONV_R8_I4)
2416                         sp [-1].data.f = (double)sp [-1].data.i;
2417                         ++ip;
2418                         MINT_IN_BREAK;
2419                 MINT_IN_CASE(MINT_CONV_R8_I8)
2420                         sp [-1].data.f = (double)sp [-1].data.l;
2421                         ++ip;
2422                         MINT_IN_BREAK;
2423                 MINT_IN_CASE(MINT_CONV_U8_I4)
2424                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
2425                         ++ip;
2426                         MINT_IN_BREAK;
2427                 MINT_IN_CASE(MINT_CONV_U8_R8)
2428                         sp [-1].data.l = (guint64)sp [-1].data.f;
2429                         ++ip;
2430                         MINT_IN_BREAK;
2431 #if 0
2432                 MINT_IN_CASE(MINT_CPOBJ) {
2433                         MonoClass *vtklass;
2434                         ++ip;
2435                         vtklass = rtm->data_items[READ32 (ip)];
2436                         ip += 2;
2437                         sp -= 2;
2438                         memcpy (sp [0].data.p, sp [1].data.p, mono_class_value_size (vtklass, NULL));
2439                         MINT_IN_BREAK;
2440                 }
2441 #endif
2442                 MINT_IN_CASE(MINT_LDOBJ) {
2443                         int size;
2444                         void *p;
2445                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2446                         ip += 2;
2447                         if (c->byval_arg.type != MONO_TYPE_VALUETYPE || c->byval_arg.data.klass->enumtype) {
2448                                 p = sp [-1].data.p;
2449                                 stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
2450                         } else {
2451                                 size = mono_class_value_size (c, NULL);
2452                                 p = sp [-1].data.p;
2453                                 sp [-1].data.p = vt_sp;
2454                                 memcpy(vt_sp, p, size);
2455                                 vt_sp += (size + 7) & ~7;
2456                         }
2457                         MINT_IN_BREAK;
2458                 }
2459                 MINT_IN_CASE(MINT_LDSTR)
2460                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
2461                         ++sp;
2462                         ip += 2;
2463                         MINT_IN_BREAK;
2464                 MINT_IN_CASE(MINT_NEWOBJ) {
2465                         MonoClass *newobj_class;
2466                         MonoMethodSignature *csig;
2467                         stackval valuetype_this;
2468                         guint32 token;
2469                         stackval retval;
2470
2471                         frame->ip = ip;
2472
2473                         token = * (guint16 *)(ip + 1);
2474                         ip += 2;
2475
2476                         child_frame.runtime_method = rtm->data_items [token];
2477                         csig = child_frame.runtime_method->method->signature;
2478                         newobj_class = child_frame.runtime_method->method->klass;
2479                         /*if (profiling_classes) {
2480                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
2481                                 count++;
2482                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
2483                         }*/
2484                                 
2485
2486                         if (newobj_class->parent == mono_defaults.array_class) {
2487                                 sp -= csig->param_count;
2488                                 o = ves_array_create (context->domain, newobj_class, csig, sp);
2489                                 goto array_constructed;
2490                         }
2491
2492                         /*
2493                          * First arg is the object.
2494                          */
2495                         if (newobj_class->valuetype) {
2496                                 if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
2497                                         child_frame.obj = vt_sp;
2498                                         valuetype_this.data.p = vt_sp;
2499                                 } else {
2500                                         memset (&valuetype_this, 0, sizeof (stackval));
2501                                         child_frame.obj = &valuetype_this;
2502                                 }
2503                         } else {
2504                                 if (newobj_class != mono_defaults.string_class) {
2505                                         context->managed_code = 0;
2506                                         o = mono_object_new (context->domain, newobj_class);
2507                                         context->managed_code = 1;
2508                                         if (*abort_requested)
2509                                                 mono_thread_interruption_checkpoint ();
2510                                         child_frame.obj = o;
2511                                 } else {
2512                                         child_frame.retval = &retval;
2513                                 }
2514                         }
2515
2516                         if (csig->param_count) {
2517                                 sp -= csig->param_count;
2518                                 child_frame.stack_args = sp;
2519                         } else {
2520                                 child_frame.stack_args = NULL;
2521                         }
2522
2523                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2524
2525                         child_frame.ip = NULL;
2526                         child_frame.ex = NULL;
2527
2528                         ves_exec_method_with_context (&child_frame, context);
2529
2530                         context->current_frame = frame;
2531
2532                         if (child_frame.ex) {
2533                                 /*
2534                                  * An exception occurred, need to run finally, fault and catch handlers..
2535                                  */
2536                                 frame->ex = child_frame.ex;
2537                                 goto handle_finally;
2538                         }
2539                         /*
2540                          * a constructor returns void, but we need to return the object we created
2541                          */
2542 array_constructed:
2543                         if (newobj_class->valuetype && !newobj_class->enumtype) {
2544                                 *sp = valuetype_this;
2545                         } else if (newobj_class == mono_defaults.string_class) {
2546                                 *sp = retval;
2547                         } else {
2548                                 sp->data.p = o;
2549                         }
2550                         ++sp;
2551                         MINT_IN_BREAK;
2552                 }
2553                 MINT_IN_CASE(MINT_CASTCLASS)
2554                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2555                         if ((o = sp [-1].data.p)) {
2556                                 if (c->marshalbyref) {
2557                                         if (!mono_object_isinst_mbyref (o, c))
2558                                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2559                                 } else {
2560                                         MonoVTable *vt = o->vtable;
2561                                         MonoClass *oklass = vt->klass;
2562                                         if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
2563                                                 if (c->interface_id > vt->max_interface_id ||
2564                                                     vt->interface_offsets [c->interface_id] == 0) {
2565                                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
2566                                                 }
2567                                         } else if (c->rank) {
2568                                                 if (!mono_object_isinst (o, c))
2569                                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
2570                                         } else if (!mono_class_has_parent (oklass, c)) {
2571                                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2572                                         }
2573                                 }
2574                         }
2575                         ip += 2;
2576                         MINT_IN_BREAK;
2577                 MINT_IN_CASE(MINT_ISINST)
2578                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2579                         if ((o = sp [-1].data.p)) {
2580                                 if (c->marshalbyref) {
2581                                         if (!mono_object_isinst_mbyref (o, c))
2582                                                 sp [-1].data.p = NULL;
2583                                 } else {
2584                                         MonoVTable *vt = o->vtable;
2585                                         MonoClass *oklass = vt->klass;
2586                                         if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
2587                                                 if (c->interface_id > vt->max_interface_id ||
2588                                                     vt->interface_offsets [c->interface_id] == 0) {
2589                                                         sp [-1].data.p = NULL;
2590                                                 }
2591                                         } else if (c->rank) {
2592                                                 if (!mono_object_isinst (o, c))
2593                                                         sp [-1].data.p = NULL;
2594                                         } else if (!mono_class_has_parent (oklass, c)) {
2595                                                 sp [-1].data.p = NULL;
2596                                         }
2597                                 }
2598                         }
2599                         ip += 2;
2600                         MINT_IN_BREAK;
2601                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
2602                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
2603                         ++ip;
2604                         MINT_IN_BREAK;
2605                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
2606                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
2607                         ++ip;
2608                         MINT_IN_BREAK;
2609                 MINT_IN_CASE(MINT_UNBOX)
2610                         c = rtm->data_items[*(guint16 *)(ip + 1)];
2611                         
2612                         o = sp [-1].data.p;
2613                         if (!o)
2614                                 THROW_EX (mono_get_exception_null_reference(), ip);
2615
2616                         if (!(mono_object_isinst (o, c) || 
2617                                   ((o->vtable->klass->rank == 0) && 
2618                                    (o->vtable->klass->element_class == c->element_class))))
2619                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2620
2621                         sp [-1].data.p = (char *)o + sizeof (MonoObject);
2622                         ip += 2;
2623                         MINT_IN_BREAK;
2624                 MINT_IN_CASE(MINT_THROW)
2625                         --sp;
2626                         frame->ex_handler = NULL;
2627                         if (!sp->data.p)
2628                                 sp->data.p = mono_get_exception_null_reference ();
2629                         THROW_EX ((MonoException *)sp->data.p, ip);
2630                         MINT_IN_BREAK;
2631                 MINT_IN_CASE(MINT_LDFLDA)
2632                         o = sp [-1].data.p;
2633                         if (!o)
2634                                 THROW_EX (mono_get_exception_null_reference (), ip);
2635                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
2636                         ip += 2;
2637                         MINT_IN_BREAK;
2638                 MINT_IN_CASE(MINT_CKNULL)
2639                         o = sp [-1].data.p;
2640                         if (!o)
2641                                 THROW_EX (mono_get_exception_null_reference (), ip);
2642                         ++ip;
2643                         MINT_IN_BREAK;
2644
2645 #define LDFLD(datamem, fieldtype) \
2646         o = sp [-1].data.p; \
2647         if (!o) \
2648                 THROW_EX (mono_get_exception_null_reference (), ip); \
2649         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
2650         ip += 2;
2651
2652                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
2653                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
2654                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
2655                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
2656                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
2657                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
2658                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
2659                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
2660                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
2661                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
2662
2663                 MINT_IN_CASE(MINT_LDFLD_VT)
2664                         o = sp [-1].data.p;
2665                         if (!o)
2666                                 THROW_EX (mono_get_exception_null_reference (), ip);
2667                         i32 = READ32(ip + 2);
2668                         sp [-1].data.p = vt_sp;
2669                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
2670                         vt_sp += (i32 + 7) & ~7;
2671                         ip += 4;
2672                         MINT_IN_BREAK;
2673
2674                 MINT_IN_CASE(MINT_LDRMFLD) {
2675                         MonoClassField *field;
2676                         char *addr;
2677
2678                         o = sp [-1].data.p;
2679                         if (!o)
2680                                 THROW_EX (mono_get_exception_null_reference (), ip);
2681                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2682                         ip += 2;
2683                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2684                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2685                                 addr = mono_load_remote_field (o, klass, field, NULL);
2686                         } else {
2687                                 addr = (char*)o + field->offset;
2688                         }                               
2689
2690                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
2691                         MINT_IN_BREAK;
2692                 }
2693
2694                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
2695                         MonoClassField *field;
2696                         char *addr;
2697
2698                         o = sp [-1].data.p;
2699                         if (!o)
2700                                 THROW_EX (mono_get_exception_null_reference (), ip);
2701                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2702                         i32 = READ32(ip + 2);
2703                         ip += 4;
2704                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2705                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2706                                 addr = mono_load_remote_field (o, klass, field, NULL);
2707                         } else {
2708                                 addr = (char*)o + field->offset;
2709                         }                               
2710
2711                         sp [-1].data.p = vt_sp;
2712                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
2713                         vt_sp += (i32 + 7) & ~7;
2714                         memcpy(sp [-1].data.p, addr, i32);
2715                         MINT_IN_BREAK;
2716                 }
2717
2718 #define STFLD(datamem, fieldtype) \
2719         o = sp [-2].data.p; \
2720         if (!o) \
2721                 THROW_EX (mono_get_exception_null_reference (), ip); \
2722         sp -= 2; \
2723         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
2724         ip += 2;
2725
2726                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
2727                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
2728                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
2729                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
2730                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
2731                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
2732                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
2733                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
2734                 MINT_IN_CASE(MINT_STFLD_O) STFLD(p, gpointer); MINT_IN_BREAK;
2735                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
2736
2737                 MINT_IN_CASE(MINT_STFLD_VT)
2738                         o = sp [-2].data.p;
2739                         if (!o)
2740                                 THROW_EX (mono_get_exception_null_reference (), ip);
2741                         i32 = READ32(ip + 2);
2742                         sp -= 2;
2743                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
2744                         vt_sp -= (i32 + 7) & ~7;
2745                         ip += 4;
2746                         MINT_IN_BREAK;
2747
2748                 MINT_IN_CASE(MINT_STRMFLD) {
2749                         MonoClassField *field;
2750
2751                         o = sp [-2].data.p;
2752                         if (!o)
2753                                 THROW_EX (mono_get_exception_null_reference (), ip);
2754                         
2755                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2756                         ip += 2;
2757
2758                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2759                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2760                                 mono_store_remote_field (o, klass, field, &sp [-1].data);
2761                         } else
2762                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
2763
2764                         sp -= 2;
2765                         MINT_IN_BREAK;
2766                 }
2767                 MINT_IN_CASE(MINT_STRMFLD_VT) {
2768                         MonoClassField *field;
2769
2770                         o = sp [-2].data.p;
2771                         if (!o)
2772                                 THROW_EX (mono_get_exception_null_reference (), ip);
2773                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2774                         i32 = READ32(ip + 2);
2775                         ip += 4;
2776
2777                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2778                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2779                                 mono_store_remote_field (o, klass, field, &sp [-1].data);
2780                         } else
2781                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
2782
2783                         sp -= 2;
2784                         vt_sp -= (i32 + 7) & ~7;
2785                         MINT_IN_BREAK;
2786                 }
2787                 MINT_IN_CASE(MINT_LDSFLDA) {
2788                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2789                         MonoVTable *vt = mono_class_vtable (context->domain, field->parent);
2790                         gpointer addr;
2791
2792                         if (!vt->initialized) {
2793                                 frame->ip = ip;
2794                                 mono_runtime_class_init (vt);
2795                         }
2796                         ip += 2;
2797
2798                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2799                                 sp->data.p = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2800                         else
2801                                 sp->data.p = (char*)(vt->data) + field->offset;
2802                         ++sp;
2803                         MINT_IN_BREAK;
2804                 }
2805                 MINT_IN_CASE(MINT_LDSFLD) {
2806                         MonoVTable *vt;
2807                         MonoClassField *field;
2808                         gpointer addr;
2809
2810                         field = rtm->data_items[*(guint16 *)(ip + 1)];
2811                         vt = rtm->data_items [*(guint16 *)(ip + 2)];
2812                         if (!vt->initialized) {
2813                                 frame->ip = ip;
2814                                 mono_runtime_class_init (vt);
2815                         }
2816                         ip += 3;
2817                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2818                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2819                         else
2820                                 addr = (char*)(vt->data) + field->offset;
2821
2822                         stackval_from_data (field->type, sp, addr, FALSE);
2823                         ++sp;
2824                         MINT_IN_BREAK;
2825                 }
2826                 MINT_IN_CASE(MINT_LDSFLD_I4) {
2827                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2828                         MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
2829                         if (!vt->initialized) {
2830                                 frame->ip = ip;
2831                                 mono_runtime_class_init (vt);
2832                         }
2833                         ip += 3;
2834                         sp->data.i = * (gint32 *)((char*)(vt->data) + field->offset);
2835                         ++sp;
2836                         MINT_IN_BREAK;
2837                 }
2838                 MINT_IN_CASE(MINT_LDSFLD_O) {
2839                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2840                         MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
2841                         if (!vt->initialized) {
2842                                 frame->ip = ip;
2843                                 mono_runtime_class_init (vt);
2844                         }
2845                         ip += 3;
2846                         sp->data.p = * (gpointer *)((char*)(vt->data) + field->offset);
2847                         ++sp;
2848                         MINT_IN_BREAK;
2849                 }
2850                 MINT_IN_CASE(MINT_LDSFLD_VT) {
2851                         MonoVTable *vt;
2852                         MonoClassField *field;
2853                         guint32 token;
2854                         gpointer addr;
2855                         int size;
2856
2857                         token = * (guint16 *)(ip + 1);
2858                         size = READ32(ip + 2);
2859                         field = rtm->data_items[token];
2860                         ip += 4;
2861                                                 
2862                         vt = mono_class_vtable (context->domain, field->parent);
2863                         if (!vt->initialized) {
2864                                 frame->ip = ip - 2;
2865                                 mono_runtime_class_init (vt);
2866                         }
2867                         
2868                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2869                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2870                         else
2871                                 addr = (char*)(vt->data) + field->offset;
2872
2873                         sp->data.p = vt_sp;
2874                         vt_sp += (size + 7) & ~7;
2875                         stackval_from_data (field->type, sp, addr, FALSE);
2876                         ++sp;
2877                         MINT_IN_BREAK;
2878                 }
2879                 MINT_IN_CASE(MINT_STSFLD) {
2880                         MonoVTable *vt;
2881                         MonoClassField *field;
2882                         guint32 token;
2883                         gpointer addr;
2884
2885                         token = * (guint16 *)(ip + 1);
2886                         field = rtm->data_items[token];
2887                         ip += 2;
2888                         --sp;
2889
2890                         vt = mono_class_vtable (context->domain, field->parent);
2891                         if (!vt->initialized) {
2892                                 frame->ip = ip - 2;
2893                                 mono_runtime_class_init (vt);
2894                         }
2895                         
2896                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2897                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2898                         else
2899                                 addr = (char*)(vt->data) + field->offset;
2900
2901                         stackval_to_data (field->type, sp, addr, FALSE);
2902                         MINT_IN_BREAK;
2903                 }
2904                 MINT_IN_CASE(MINT_STSFLD_VT) {
2905                         MonoVTable *vt;
2906                         MonoClassField *field;
2907                         guint32 token;
2908                         gpointer addr;
2909                         int size;
2910
2911                         token = * (guint16 *)(ip + 1);
2912                         size = READ32(ip + 2);
2913                         field = rtm->data_items[token];
2914                         ip += 4;
2915                                                 
2916                         vt = mono_class_vtable (context->domain, field->parent);
2917                         if (!vt->initialized) {
2918                                 frame->ip = ip - 2;
2919                                 mono_runtime_class_init (vt);
2920                         }
2921                         
2922                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2923                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2924                         else
2925                                 addr = (char*)(vt->data) + field->offset;
2926                         --sp;
2927                         stackval_to_data (field->type, sp, addr, FALSE);
2928                         vt_sp -= (size + 7) & ~7;
2929                         MINT_IN_BREAK;
2930                 }
2931                 MINT_IN_CASE(MINT_STOBJ_VT) {
2932                         int size;
2933                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2934                         ip += 2;
2935                         size = mono_class_value_size (c, NULL);
2936                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
2937                         vt_sp -= (size + 7) & ~7;
2938                         sp -= 2;
2939                         MINT_IN_BREAK;
2940                 }
2941                 MINT_IN_CASE(MINT_STOBJ) {
2942                         int size;
2943                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2944                         ip += 2;
2945                         size = mono_class_value_size (c, NULL);
2946                         memcpy(sp [-2].data.p, &sp [-1].data, size);
2947                         sp -= 2;
2948                         MINT_IN_BREAK;
2949                 }
2950                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
2951                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
2952                                 THROW_EX (mono_get_exception_overflow (), ip);
2953                         sp [-1].data.i = (guint32)sp [-1].data.f;
2954                         ++ip;
2955                         MINT_IN_BREAK;
2956                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
2957                         if (sp [-1].data.i < 0)
2958                                 THROW_EX (mono_get_exception_overflow (), ip);
2959                         sp [-1].data.l = sp [-1].data.i;
2960                         ++ip;
2961                         MINT_IN_BREAK;
2962                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
2963                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
2964                         if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807LL)
2965                                 THROW_EX (mono_get_exception_overflow (), ip);
2966                         sp [-1].data.l = (guint64)sp [-1].data.f;
2967                         ++ip;
2968                         MINT_IN_BREAK;
2969                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
2970                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
2971                                 THROW_EX (mono_get_exception_overflow (), ip);
2972                         sp [-1].data.l = (gint64)sp [-1].data.f;
2973                         ++ip;
2974                         MINT_IN_BREAK;
2975                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
2976                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
2977                                 THROW_EX (mono_get_exception_overflow (), ip);
2978                         sp [-1].data.i = (mono_u)sp [-1].data.l;
2979                         ++ip;
2980                         MINT_IN_BREAK;
2981                 MINT_IN_CASE(MINT_BOX)
2982                         c = rtm->data_items [* (guint16 *)(ip + 1)];
2983
2984                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
2985                                 int size = mono_class_value_size (c, NULL);
2986                                 sp [-1].data.p = mono_value_box (context->domain, c, sp [-1].data.p);
2987                                 size = (size + 7) & ~7;
2988                                 vt_sp -= size;
2989                         }                               
2990                         else {
2991                                 stackval_to_data (&c->byval_arg, &sp [-1], (char*)&sp [-1], FALSE);
2992                                 sp [-1].data.p = mono_value_box (context->domain, c, &sp [-1]);
2993                         }
2994                         ip += 2;
2995                         MINT_IN_BREAK;
2996                 MINT_IN_CASE(MINT_NEWARR)
2997                         sp [-1].data.p = (MonoObject*) mono_array_new (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i);
2998                         ip += 2;
2999                         /*if (profiling_classes) {
3000                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3001                                 count++;
3002                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3003                         }*/
3004
3005                         MINT_IN_BREAK;
3006                 MINT_IN_CASE(MINT_LDLEN)
3007                         o = sp [-1].data.p;
3008                         if (!o)
3009                                 THROW_EX (mono_get_exception_null_reference (), ip);
3010                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3011                         ++ip;
3012                         MINT_IN_BREAK;
3013                 MINT_IN_CASE(MINT_GETCHR) {
3014                         MonoString *s;
3015                         s = sp [-2].data.p;
3016                         if (!s)
3017                                 THROW_EX (mono_get_exception_null_reference (), ip);
3018                         i32 = sp [-1].data.i;
3019                         if (i32 < 0 || i32 >= mono_string_length (s))
3020                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3021                         --sp;
3022                         sp [-1].data.i = mono_string_chars(s)[i32];
3023                         ++ip;
3024                         MINT_IN_BREAK;
3025                 }
3026                 MINT_IN_CASE(MINT_STRLEN)
3027                         ++ip;
3028                         sp [-1].data.i = mono_string_length ((MonoString*)sp [-1].data.p);
3029                         MINT_IN_BREAK;
3030                 MINT_IN_CASE(MINT_ARRAY_RANK)
3031                         o = sp [-1].data.p;
3032                         if (!o)
3033                                 THROW_EX (mono_get_exception_null_reference (), ip);
3034                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
3035                         ip++;
3036                         MINT_IN_BREAK;
3037                 MINT_IN_CASE(MINT_LDELEMA) {
3038                         guint32 esize;
3039                         mono_u aindex;
3040                         
3041                         /*token = READ32 (ip)*/;
3042                         ip += 2;
3043                         sp -= 2;
3044
3045                         o = sp [0].data.p;
3046
3047                         aindex = sp [1].data.i;
3048                         if (aindex >= mono_array_length ((MonoArray *) o))
3049                                 THROW_EX (mono_get_exception_index_out_of_range (), ip - 2);
3050
3051                         /* check the array element corresponds to token */
3052                         esize = mono_array_element_size (((MonoArray *) o)->obj.vtable->klass);
3053                         
3054                         sp->data.p = mono_array_addr_with_size ((MonoArray *) o, esize, aindex);
3055                         ++sp;
3056                         MINT_IN_BREAK;
3057                 }
3058                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
3059                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
3060                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
3061                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
3062                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
3063                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
3064                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
3065                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
3066                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
3067                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
3068                 MINT_IN_CASE(MINT_LDELEM_REF) {
3069                         MonoArray *o;
3070                         mono_u aindex;
3071
3072                         sp -= 2;
3073
3074                         o = sp [0].data.p;
3075                         if (!o)
3076                                 THROW_EX (mono_get_exception_null_reference (), ip);
3077
3078                         aindex = sp [1].data.i;
3079                         if (aindex >= mono_array_length (o))
3080                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3081
3082                         /*
3083                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3084                          */
3085                         switch (*ip) {
3086                         case MINT_LDELEM_I1:
3087                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
3088                                 break;
3089                         case MINT_LDELEM_U1:
3090                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
3091                                 break;
3092                         case MINT_LDELEM_I2:
3093                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
3094                                 break;
3095                         case MINT_LDELEM_U2:
3096                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
3097                                 break;
3098                         case MINT_LDELEM_I:
3099                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
3100                                 break;
3101                         case MINT_LDELEM_I4:
3102                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
3103                                 break;
3104                         case MINT_LDELEM_U4:
3105                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
3106                                 break;
3107                         case MINT_LDELEM_I8:
3108                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
3109                                 break;
3110                         case MINT_LDELEM_R4:
3111                                 sp [0].data.f = mono_array_get (o, float, aindex);
3112                                 break;
3113                         case MINT_LDELEM_R8:
3114                                 sp [0].data.f = mono_array_get (o, double, aindex);
3115                                 break;
3116                         case MINT_LDELEM_REF:
3117                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
3118                                 break;
3119                         default:
3120                                 ves_abort();
3121                         }
3122
3123                         ++ip;
3124                         ++sp;
3125                         MINT_IN_BREAK;
3126                 }
3127                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
3128                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
3129                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
3130                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
3131                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
3132                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
3133                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
3134                 MINT_IN_CASE(MINT_STELEM_REF) {
3135                         mono_u aindex;
3136
3137                         sp -= 3;
3138
3139                         o = sp [0].data.p;
3140                         if (!o)
3141                                 THROW_EX (mono_get_exception_null_reference (), ip);
3142
3143                         aindex = sp [1].data.i;
3144                         if (aindex >= mono_array_length ((MonoArray *)o))
3145                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3146
3147                         switch (*ip) {
3148                         case MINT_STELEM_I:
3149                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
3150                                 break;
3151                         case MINT_STELEM_I1:
3152                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
3153                                 break;
3154                         case MINT_STELEM_I2:
3155                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
3156                                 break;
3157                         case MINT_STELEM_I4:
3158                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
3159                                 break;
3160                         case MINT_STELEM_I8:
3161                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
3162                                 break;
3163                         case MINT_STELEM_R4:
3164                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
3165                                 break;
3166                         case MINT_STELEM_R8:
3167                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
3168                                 break;
3169                         case MINT_STELEM_REF:
3170                                 if (sp [2].data.p && !mono_object_isinst (sp [2].data.p, mono_object_class (o)->element_class))
3171                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
3172                                 mono_array_set ((MonoArray *)o, gpointer, aindex, sp [2].data.p);
3173                                 break;
3174                         default:
3175                                 ves_abort();
3176                         }
3177
3178                         ++ip;
3179                         MINT_IN_BREAK;
3180                 }
3181                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
3182                         if (sp [-1].data.i < 0)
3183                                 THROW_EX (mono_get_exception_overflow (), ip);
3184                         ++ip;
3185                         MINT_IN_BREAK;
3186                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
3187                         if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
3188                                 THROW_EX (mono_get_exception_overflow (), ip);
3189                         sp [-1].data.i = (gint32) sp [-1].data.l;
3190                         ++ip;
3191                         MINT_IN_BREAK;
3192                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
3193                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
3194                                 THROW_EX (mono_get_exception_overflow (), ip);
3195                         sp [-1].data.i = (gint32) sp [-1].data.f;
3196                         ++ip;
3197                         MINT_IN_BREAK;
3198                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
3199                         if (sp [-1].data.i < 0)
3200                                 THROW_EX (mono_get_exception_overflow (), ip);
3201                         ++ip;
3202                         MINT_IN_BREAK;
3203                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
3204                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
3205                                 THROW_EX (mono_get_exception_overflow (), ip);
3206                         sp [-1].data.i = (guint32) sp [-1].data.l;
3207                         ++ip;
3208                         MINT_IN_BREAK;
3209                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
3210                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3211                                 THROW_EX (mono_get_exception_overflow (), ip);
3212                         sp [-1].data.i = (guint32) sp [-1].data.f;
3213                         ++ip;
3214                         MINT_IN_BREAK;
3215                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
3216                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
3217                                 THROW_EX (mono_get_exception_overflow (), ip);
3218                         ++ip;
3219                         MINT_IN_BREAK;
3220                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
3221                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
3222                                 THROW_EX (mono_get_exception_overflow (), ip);
3223                         sp [-1].data.i = (gint16) sp [-1].data.l;
3224                         ++ip;
3225                         MINT_IN_BREAK;
3226                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
3227                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
3228                                 THROW_EX (mono_get_exception_overflow (), ip);
3229                         sp [-1].data.i = (gint16) sp [-1].data.f;
3230                         ++ip;
3231                         MINT_IN_BREAK;
3232                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
3233                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
3234                                 THROW_EX (mono_get_exception_overflow (), ip);
3235                         ++ip;
3236                         MINT_IN_BREAK;
3237                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
3238                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
3239                                 THROW_EX (mono_get_exception_overflow (), ip);
3240                         sp [-1].data.i = (guint16) sp [-1].data.l;
3241                         ++ip;
3242                         MINT_IN_BREAK;
3243                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
3244                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
3245                                 THROW_EX (mono_get_exception_overflow (), ip);
3246                         sp [-1].data.i = (guint16) sp [-1].data.f;
3247                         ++ip;
3248                         MINT_IN_BREAK;
3249                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
3250                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
3251                                 THROW_EX (mono_get_exception_overflow (), ip);
3252                         ++ip;
3253                         MINT_IN_BREAK;
3254                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
3255                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
3256                                 THROW_EX (mono_get_exception_overflow (), ip);
3257                         sp [-1].data.i = (gint8) sp [-1].data.l;
3258                         ++ip;
3259                         MINT_IN_BREAK;
3260                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
3261                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
3262                                 THROW_EX (mono_get_exception_overflow (), ip);
3263                         sp [-1].data.i = (gint8) sp [-1].data.f;
3264                         ++ip;
3265                         MINT_IN_BREAK;
3266                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
3267                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
3268                                 THROW_EX (mono_get_exception_overflow (), ip);
3269                         ++ip;
3270                         MINT_IN_BREAK;
3271                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
3272                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
3273                                 THROW_EX (mono_get_exception_overflow (), ip);
3274                         sp [-1].data.i = (guint8) sp [-1].data.l;
3275                         ++ip;
3276                         MINT_IN_BREAK;
3277                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
3278                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
3279                                 THROW_EX (mono_get_exception_overflow (), ip);
3280                         sp [-1].data.i = (guint8) sp [-1].data.f;
3281                         ++ip;
3282                         MINT_IN_BREAK;
3283 #if 0
3284                 MINT_IN_CASE(MINT_LDELEM) 
3285                 MINT_IN_CASE(MINT_STELEM) 
3286                 MINT_IN_CASE(MINT_UNBOX_ANY) 
3287
3288                 MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
3289 #endif
3290                 MINT_IN_CASE(MINT_CKFINITE)
3291                         if (!finite(sp [-1].data.f))
3292                                 THROW_EX (mono_get_exception_arithmetic (), ip);
3293                         ++ip;
3294                         MINT_IN_BREAK;
3295 #if 0
3296                 MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
3297 #endif
3298                 MINT_IN_CASE(MINT_LDTOKEN)
3299                         sp->data.p = vt_sp;
3300                         vt_sp += 8;
3301                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
3302                         ip += 2;
3303                         ++sp;
3304                         MINT_IN_BREAK;
3305                 MINT_IN_CASE(MINT_ADD_OVF_I4)
3306                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3307                                 THROW_EX (mono_get_exception_overflow (), ip);
3308                         BINOP(i, +);
3309                         MINT_IN_BREAK;
3310                 MINT_IN_CASE(MINT_ADD_OVF_I8)
3311                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3312                                 THROW_EX (mono_get_exception_overflow (), ip);
3313                         BINOP(l, +);
3314                         MINT_IN_BREAK;
3315                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
3316                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3317                                 THROW_EX (mono_get_exception_overflow (), ip);
3318                         BINOP_CAST(i, +, guint32);
3319                         MINT_IN_BREAK;
3320                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
3321                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3322                                 THROW_EX (mono_get_exception_overflow (), ip);
3323                         BINOP_CAST(l, +, guint64);
3324                         MINT_IN_BREAK;
3325                 MINT_IN_CASE(MINT_MUL_OVF_I4)
3326                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3327                                 THROW_EX (mono_get_exception_overflow (), ip);
3328                         BINOP(i, *);
3329                         MINT_IN_BREAK;
3330                 MINT_IN_CASE(MINT_MUL_OVF_I8)
3331                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3332                                 THROW_EX (mono_get_exception_overflow (), ip);
3333                         BINOP(l, *);
3334                         MINT_IN_BREAK;
3335                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
3336                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3337                                 THROW_EX (mono_get_exception_overflow (), ip);
3338                         BINOP_CAST(i, *, guint32);
3339                         MINT_IN_BREAK;
3340                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
3341                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3342                                 THROW_EX (mono_get_exception_overflow (), ip);
3343                         BINOP_CAST(l, *, guint64);
3344                         MINT_IN_BREAK;
3345                 MINT_IN_CASE(MINT_SUB_OVF_I4)
3346                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3347                                 THROW_EX (mono_get_exception_overflow (), ip);
3348                         BINOP(i, -);
3349                         MINT_IN_BREAK;
3350                 MINT_IN_CASE(MINT_SUB_OVF_I8)
3351                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3352                                 THROW_EX (mono_get_exception_overflow (), ip);
3353                         BINOP(l, -);
3354                         MINT_IN_BREAK;
3355                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
3356                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3357                                 THROW_EX (mono_get_exception_overflow (), ip);
3358                         BINOP_CAST(i, -, guint32);
3359                         MINT_IN_BREAK;
3360                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
3361                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3362                                 THROW_EX (mono_get_exception_overflow (), ip);
3363                         BINOP_CAST(l, -, guint64);
3364                         MINT_IN_BREAK;
3365                 MINT_IN_CASE(MINT_ENDFINALLY)
3366                         if (finally_ips) {
3367                                 ip = finally_ips->data;
3368                                 finally_ips = g_slist_remove (finally_ips, ip);
3369                                 goto main_loop;
3370                         }
3371                         if (frame->ex)
3372                                 goto handle_fault;
3373                         ves_abort();
3374                         MINT_IN_BREAK;
3375                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
3376                 MINT_IN_CASE(MINT_LEAVE_S)
3377                         while (sp > frame->stack) {
3378                                 --sp;
3379                         }
3380                         frame->ip = ip;
3381                         if (*ip == MINT_LEAVE_S) {
3382                                 ip += (short) *(ip + 1);
3383                         } else {
3384                                 ip += (gint32) READ32 (ip + 1);
3385                         }
3386                         endfinally_ip = ip;
3387                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
3388                                 frame->ex_handler = NULL;
3389                                 frame->ex = NULL;
3390                         }
3391                         goto handle_finally;
3392                         MINT_IN_BREAK;
3393                 MINT_IN_CASE(MINT_ICALL_P_V) {
3394                         void (*func)(gpointer) = rtm->data_items [*(guint16 *)(ip + 1)];
3395                         ip += 2;
3396
3397                         func (sp [-1].data.p);
3398                         sp --;
3399                         MINT_IN_BREAK;
3400                 }
3401                 MINT_IN_CASE(MINT_ICALL_P_P) {
3402                         gpointer (*func)(gpointer) = rtm->data_items [*(guint16 *)(ip + 1)];
3403                         ip += 2;
3404
3405                         sp [-1].data.p = func (sp [-1].data.p);
3406                         MINT_IN_BREAK;
3407                 }
3408                 MINT_IN_CASE(MINT_ICALL_PP_V) {
3409                         void (*func)(gpointer,gpointer) = rtm->data_items [*(guint16 *)(ip + 1)];
3410                         ip += 2;
3411                         sp -= 2;
3412
3413                         func (sp [0].data.p, sp [1].data.p);
3414                         MINT_IN_BREAK;
3415                 }
3416                 MINT_IN_CASE(MINT_ICALL_PP_P) {
3417                         gpointer (*func)(gpointer,gpointer) = rtm->data_items [*(guint16 *)(ip + 1)];
3418                         ip += 2;
3419                         --sp;
3420
3421                         sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
3422                         MINT_IN_BREAK;
3423                 }
3424                 MINT_IN_CASE(MINT_ICALL_PPP_V) {
3425                         void (*func)(gpointer,gpointer,gpointer) = rtm->data_items [*(guint16 *)(ip + 1)];
3426                         ip += 2;
3427                         sp -= 3;
3428
3429                         func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
3430                         MINT_IN_BREAK;
3431                 }
3432                 MINT_IN_CASE(MINT_MONO_LDPTR) 
3433                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
3434                         ip += 2;
3435                         ++sp;
3436                         MINT_IN_BREAK;
3437                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
3438                         sp->data.p = mono_object_new (context->domain, rtm->data_items [*(guint16 *)(ip + 1)]);
3439                         ip += 2;
3440                         sp++;
3441                         MINT_IN_BREAK;
3442                 MINT_IN_CASE(MINT_MONO_FREE)
3443                         ++ip;
3444                         --sp;
3445                         g_free (sp->data.p);
3446                         MINT_IN_BREAK;
3447                 MINT_IN_CASE(MINT_MONO_RETOBJ)
3448                         ++ip;
3449                         sp--;
3450                         stackval_from_data (frame->runtime_method->method->signature->ret, frame->retval, sp->data.p, frame->runtime_method->method->signature->pinvoke);
3451                         if (sp > frame->stack)
3452                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
3453                         goto exit_frame;
3454
3455 #define RELOP(datamem, op) \
3456         --sp; \
3457         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
3458         ++ip;
3459                 MINT_IN_CASE(MINT_CEQ_I4)
3460                         RELOP(i, ==);
3461                         MINT_IN_BREAK;
3462                 MINT_IN_CASE(MINT_CEQ0_I4)
3463                         sp [-1].data.i = (sp [-1].data.i == 0);
3464                         ++ip;
3465                         MINT_IN_BREAK;
3466                 MINT_IN_CASE(MINT_CEQ_I8)
3467                         RELOP(l, ==);
3468                         MINT_IN_BREAK;
3469                 MINT_IN_CASE(MINT_CEQ_R8)
3470                         --sp; 
3471                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3472                                 sp [-1].data.i = 0;
3473                         else
3474                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
3475                         ++ip;
3476                         MINT_IN_BREAK;
3477                 MINT_IN_CASE(MINT_CGT_I4)
3478                         RELOP(i, >);
3479                         MINT_IN_BREAK;
3480                 MINT_IN_CASE(MINT_CGT_I8)
3481                         RELOP(l, >);
3482                         MINT_IN_BREAK;
3483                 MINT_IN_CASE(MINT_CGT_R8)
3484                         --sp; 
3485                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3486                                 sp [-1].data.i = 0;
3487                         else
3488                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3489                         ++ip;
3490                         MINT_IN_BREAK;
3491
3492 #define RELOP_CAST(datamem, op, type) \
3493         --sp; \
3494         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3495         ++ip;
3496
3497                 MINT_IN_CASE(MINT_CGT_UN_I4)
3498                         RELOP_CAST(i, >, guint32);
3499                         MINT_IN_BREAK;
3500                 MINT_IN_CASE(MINT_CGT_UN_I8)
3501                         RELOP_CAST(l, >, guint64);
3502                         MINT_IN_BREAK;
3503                 MINT_IN_CASE(MINT_CGT_UN_R8)
3504                         --sp; 
3505                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3506                                 sp [-1].data.i = 1;
3507                         else
3508                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3509                         ++ip;
3510                         MINT_IN_BREAK;
3511                 MINT_IN_CASE(MINT_CLT_I4)
3512                         RELOP(i, <);
3513                         MINT_IN_BREAK;
3514                 MINT_IN_CASE(MINT_CLT_I8)
3515                         RELOP(l, <);
3516                         MINT_IN_BREAK;
3517                 MINT_IN_CASE(MINT_CLT_R8)
3518                         --sp; 
3519                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3520                                 sp [-1].data.i = 0;
3521                         else
3522                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3523                         ++ip;
3524                         MINT_IN_BREAK;
3525                 MINT_IN_CASE(MINT_CLT_UN_I4)
3526                         RELOP_CAST(i, <, guint32);
3527                         MINT_IN_BREAK;
3528                 MINT_IN_CASE(MINT_CLT_UN_I8)
3529                         RELOP_CAST(l, <, guint64);
3530                         MINT_IN_BREAK;
3531                 MINT_IN_CASE(MINT_CLT_UN_R8)
3532                         --sp; 
3533                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3534                                 sp [-1].data.i = 1;
3535                         else
3536                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3537                         ++ip;
3538                         MINT_IN_BREAK;
3539                 MINT_IN_CASE(MINT_LDFTN) {
3540                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3541                         ++sp;
3542                         ip += 2;
3543                         MINT_IN_BREAK;
3544                 }
3545                 MINT_IN_CASE(MINT_LDVIRTFTN) {
3546                         RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
3547                         ip += 2;
3548                         --sp;
3549                         if (!sp->data.p)
3550                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
3551                                 
3552                         sp->data.p = get_virtual_method (m, sp->data.p);
3553                         ++sp;
3554                         MINT_IN_BREAK;
3555                 }
3556
3557                 MINT_IN_CASE(MINT_LDTHIS)
3558                         sp->data.p = frame->obj;
3559                         ++ip;
3560                         ++sp; 
3561                         MINT_IN_BREAK;
3562                 MINT_IN_CASE(MINT_STTHIS)
3563                         --sp; 
3564                         frame->obj = sp->data.p;
3565                         ++ip;
3566                         MINT_IN_BREAK;
3567                 MINT_IN_CASE(MINT_LDTHISA)
3568                         sp->data.p = &frame->obj;
3569                         ++ip;
3570                         ++sp; 
3571                         MINT_IN_BREAK;
3572
3573 #define LDARG(datamem, argtype) \
3574         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
3575         ip += 2; \
3576         ++sp; 
3577         
3578                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
3579                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
3580                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
3581                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
3582                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
3583                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
3584                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
3585                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
3586                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
3587                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
3588
3589                 MINT_IN_CASE(MINT_LDARG_VT)
3590                         sp->data.p = vt_sp;
3591                         i32 = READ32(ip + 2);
3592                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
3593                         vt_sp += (i32 + 7) & ~7;
3594                         ip += 4;
3595                         ++sp;
3596                         MINT_IN_BREAK;
3597
3598 #define STARG(datamem, argtype) \
3599         --sp; \
3600         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3601         ip += 2; \
3602         
3603                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
3604                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
3605                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
3606                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
3607                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
3608                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
3609                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
3610                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
3611                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
3612                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
3613
3614                 MINT_IN_CASE(MINT_STARG_VT) 
3615                         i32 = READ32(ip + 2);
3616                         --sp;
3617                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
3618                         vt_sp -= (i32 + 7) & ~7;
3619                         ip += 4;
3620                         MINT_IN_BREAK;
3621
3622 #define STINARG(datamem, argtype) \
3623         do { \
3624                 int n = * (guint16 *)(ip + 1); \
3625                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
3626                 ip += 2; \
3627         } while (0)
3628         
3629                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
3630                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
3631                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
3632                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
3633                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
3634                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
3635                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
3636                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
3637                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
3638                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
3639
3640                 MINT_IN_CASE(MINT_STINARG_VT) {
3641                         int n = * (guint16 *)(ip + 1);
3642                         i32 = READ32(ip + 2);
3643                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
3644                         ip += 4;
3645                         MINT_IN_BREAK;
3646                 }
3647
3648                 MINT_IN_CASE(MINT_LDARGA)
3649                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
3650                         ip += 2;
3651                         ++sp;
3652                         MINT_IN_BREAK;
3653
3654 #define LDLOC(datamem, argtype) \
3655         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
3656         ip += 2; \
3657         ++sp; 
3658         
3659                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
3660                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
3661                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
3662                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
3663                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
3664                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
3665                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
3666                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
3667                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
3668                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
3669
3670                 MINT_IN_CASE(MINT_LDLOC_VT)
3671                         sp->data.p = vt_sp;
3672                         i32 = READ32(ip + 2);
3673                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
3674                         vt_sp += (i32 + 7) & ~7;
3675                         ip += 4;
3676                         ++sp;
3677                         MINT_IN_BREAK;
3678
3679                 MINT_IN_CASE(MINT_LDLOCA_S)
3680                         sp->data.p = locals + * (guint16 *)(ip + 1);
3681                         ip += 2;
3682                         ++sp;
3683                         MINT_IN_BREAK;
3684
3685 #define STLOC(datamem, argtype) \
3686         --sp; \
3687         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3688         ip += 2;
3689         
3690                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
3691                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
3692                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
3693                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
3694                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
3695                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
3696                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
3697                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
3698                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
3699                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
3700
3701 #define STLOC_NP(datamem, argtype) \
3702         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
3703         ip += 2;
3704
3705                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
3706                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
3707
3708                 MINT_IN_CASE(MINT_STLOC_VT)
3709                         i32 = READ32(ip + 2);
3710                         --sp;
3711                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
3712                         vt_sp -= (i32 + 7) & ~7;
3713                         ip += 4;
3714                         MINT_IN_BREAK;
3715
3716                 MINT_IN_CASE(MINT_LOCALLOC)
3717                         if (sp != frame->stack + 1) /*FIX?*/
3718                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
3719                         sp [-1].data.p = alloca (sp [-1].data.i);
3720                         ++ip;
3721                         MINT_IN_BREAK;
3722 #if 0
3723                 MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
3724 #endif
3725                 MINT_IN_CASE(MINT_INITOBJ)
3726                         --sp;
3727                         memset (sp->data.vt, 0, READ32(ip + 1));
3728                         ip += 3;
3729                         MINT_IN_BREAK;
3730                 MINT_IN_CASE(MINT_CPBLK)
3731                         sp -= 3;
3732                         if (!sp [0].data.p || !sp [1].data.p)
3733                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
3734                         ++ip;
3735                         /* FIXME: value and size may be int64... */
3736                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
3737                         MINT_IN_BREAK;
3738 #if 0
3739                 MINT_IN_CASE(MINT_CONSTRAINED_) {
3740                         guint32 token;
3741                         /* FIXME: implement */
3742                         ++ip;
3743                         token = READ32 (ip);
3744                         ip += 2;
3745                         MINT_IN_BREAK;
3746                 }
3747 #endif
3748                 MINT_IN_CASE(MINT_INITBLK)
3749                         sp -= 3;
3750                         if (!sp [0].data.p)
3751                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
3752                         ++ip;
3753                         /* FIXME: value and size may be int64... */
3754                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
3755                         MINT_IN_BREAK;
3756 #if 0
3757                 MINT_IN_CASE(MINT_NO_)
3758                         /* FIXME: implement */
3759                         ip += 2;
3760                         MINT_IN_BREAK;
3761 #endif
3762                 MINT_IN_CASE(MINT_RETHROW)
3763                         /* 
3764                          * need to clarify what this should actually do:
3765                          * start the search from the last found handler in
3766                          * this method or continue in the caller or what.
3767                          * Also, do we need to run finally/fault handlers after a retrow?
3768                          * Well, this implementation will follow the usual search
3769                          * for an handler, considering the current ip as throw spot.
3770                          * We need to NULL frame->ex_handler for the later code to
3771                          * actually run the new found handler.
3772                          */
3773                         frame->ex_handler = NULL;
3774                         THROW_EX (frame->ex, ip - 1);
3775                         MINT_IN_BREAK;
3776                 MINT_IN_DEFAULT
3777                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
3778                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
3779                 }
3780         }
3781
3782         g_assert_not_reached ();
3783         /*
3784          * Exception handling code.
3785          * The exception object is stored in frame->ex.
3786          */
3787
3788         handle_exception:
3789         {
3790                 int i;
3791                 guint32 ip_offset;
3792                 MonoInvocation *inv;
3793                 MonoExceptionClause *clause;
3794                 /*char *message;*/
3795                 MonoObject *ex_obj;
3796
3797 #if DEBUG_INTERP
3798                 if (tracing)
3799                         g_print ("* Handling exception '%s' at IL_%04x\n", 
3800                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
3801                                 rtm == NULL ? 0 : frame->ip - rtm->code);
3802 #endif
3803                 if (die_on_exception)
3804                         goto die_on_ex;
3805
3806                 for (inv = frame; inv; inv = inv->parent) {
3807                         MonoMethod *method;
3808                         if (inv->runtime_method == NULL)
3809                                 continue;
3810                         method = inv->runtime_method->method;
3811                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
3812                                 continue;
3813                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
3814                                 continue;
3815                         if (inv->ip == NULL)
3816                                 continue;
3817                         ip_offset = inv->ip - inv->runtime_method->code;
3818                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
3819                         for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
3820                                 clause = &inv->runtime_method->clauses [i];
3821                                 if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3822                                         if (!clause->flags) {
3823                                                 if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (method->klass->image, clause->token_or_filter))) {
3824                                                         /* 
3825                                                          * OK, we found an handler, now we need to execute the finally
3826                                                          * and fault blocks before branching to the handler code.
3827                                                          */
3828                                                         inv->ex_handler = clause;
3829 #if DEBUG_INTERP
3830                                                         if (tracing)
3831                                                                 g_print ("* Found handler at '%s'\n", method->name);
3832 #endif
3833                                                         goto handle_finally;
3834                                                 }
3835                                         } else {
3836                                                 /* FIXME: handle filter clauses */
3837                                                 g_assert (0);
3838                                         }
3839                                 }
3840                         }
3841                 }
3842                 /*
3843                  * If we get here, no handler was found: print a stack trace.
3844                  */
3845                 for (inv = frame; inv; inv = inv->parent) {
3846                         if (inv->invoke_trap)
3847                                 goto handle_finally;
3848                 }
3849 die_on_ex:
3850                 ex_obj = (MonoObject*)frame->ex;
3851                 mono_unhandled_exception (ex_obj);
3852                 exit (1);
3853         }
3854         handle_finally:
3855         {
3856                 int i;
3857                 guint32 ip_offset;
3858                 MonoExceptionClause *clause;
3859                 GSList *old_list = finally_ips;
3860                 MonoMethod *method = frame->runtime_method->method;
3861                 MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
3862                 
3863 #if DEBUG_INTERP
3864                 if (tracing)
3865                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
3866 #endif
3867                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
3868                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
3869                         goto exit_frame;
3870                 }
3871                 ip_offset = frame->ip - rtm->code;
3872
3873                 if (endfinally_ip != NULL)
3874                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
3875                 for (i = 0; i < header->num_clauses; ++i)
3876                         if (frame->ex_handler == &rtm->clauses [i])
3877                                 break;
3878                 while (i > 0) {
3879                         --i;
3880                         clause = &rtm->clauses [i];
3881                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
3882                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
3883                                         ip = rtm->code + clause->handler_offset;
3884                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
3885 #if DEBUG_INTERP
3886                                         if (tracing)
3887                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
3888 #endif
3889                                 }
3890                         }
3891                 }
3892
3893                 endfinally_ip = NULL;
3894
3895                 if (old_list != finally_ips && finally_ips) {
3896                         ip = finally_ips->data;
3897                         finally_ips = g_slist_remove (finally_ips, ip);
3898                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
3899                         goto main_loop;
3900                 }
3901
3902                 /*
3903                  * If an exception is set, we need to execute the fault handler, too,
3904                  * otherwise, we continue normally.
3905                  */
3906                 if (frame->ex)
3907                         goto handle_fault;
3908                 ves_abort();
3909         }
3910         handle_fault:
3911         {
3912                 int i;
3913                 guint32 ip_offset;
3914                 MonoExceptionClause *clause;
3915                 MonoMethodHeader *header = ((MonoMethodNormal *)frame->runtime_method->method)->header;
3916                 
3917 #if DEBUG_INTERP
3918                 if (tracing)
3919                         g_print ("* Handle fault\n");
3920 #endif
3921                 ip_offset = frame->ip - rtm->code;
3922                 for (i = 0; i < header->num_clauses; ++i) {
3923                         clause = &rtm->clauses [i];
3924                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3925                                 ip = rtm->code + clause->handler_offset;
3926 #if DEBUG_INTERP
3927                                 if (tracing)
3928                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
3929 #endif
3930                                 goto main_loop;
3931                         }
3932                 }
3933                 /*
3934                  * If the handler for the exception was found in this method, we jump
3935                  * to it right away, otherwise we return and let the caller run
3936                  * the finally, fault and catch blocks.
3937                  * This same code should be present in the endfault opcode, but it
3938                  * is corrently not assigned in the ECMA specs: LAMESPEC.
3939                  */
3940                 if (frame->ex_handler) {
3941 #if DEBUG_INTERP
3942                         if (tracing)
3943                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
3944 #endif
3945                         ip = rtm->code + frame->ex_handler->handler_offset;
3946                         sp = frame->stack;
3947                         vt_sp = (char *)sp + rtm->stack_size;
3948                         sp->data.p = frame->ex;
3949                         ++sp;
3950                         goto main_loop;
3951                 }
3952                 goto exit_frame;
3953         }
3954 exit_frame:
3955         DEBUG_LEAVE ();
3956 }
3957
3958 void
3959 ves_exec_method (MonoInvocation *frame)
3960 {
3961         ThreadContext *context = TlsGetValue (thread_context_id);
3962         ThreadContext context_struct;
3963         jmp_buf env;
3964
3965         frame->ex = NULL;
3966
3967         if (setjmp(env)) {
3968                 mono_unhandled_exception ((MonoObject*)frame->ex);
3969                 return;
3970         }
3971         if (context == NULL) {
3972                 context = &context_struct;
3973                 context_struct.domain = mono_domain_get ();
3974                 context_struct.base_frame = frame;
3975                 context_struct.current_frame = NULL;
3976                 context_struct.env_frame = frame;
3977                 context_struct.current_env = &env;
3978                 context_struct.search_for_handler = 0;
3979                 context_struct.managed_code = 0;
3980                 TlsSetValue (thread_context_id, context);
3981         }
3982         frame->ip = NULL;
3983         frame->parent = context->current_frame;
3984         frame->runtime_method = mono_interp_get_runtime_method (frame->method);
3985         context->managed_code = 1;
3986         ves_exec_method_with_context(frame, context);
3987         context->managed_code = 0;
3988         if (frame->ex) {
3989                 if (context != &context_struct && context->current_env) {
3990                         context->env_frame->ex = frame->ex;
3991                         longjmp (*context->current_env, 1);
3992                 }
3993                 else
3994                         mono_unhandled_exception ((MonoObject*)frame->ex);
3995         }
3996         if (context->base_frame == frame)
3997                 TlsSetValue (thread_context_id, NULL);
3998         else
3999                 context->current_frame = frame->parent;
4000 }
4001
4002 static int 
4003 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4004 {
4005         MonoImage *image = mono_assembly_get_image (assembly);
4006         MonoMethod *method;
4007         MonoObject *exc = NULL;
4008         int rval;
4009
4010         method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
4011         if (!method)
4012                 g_error ("No entry point method found in %s", mono_image_get_filename (image));
4013
4014         rval = mono_runtime_run_main (method, argc, argv, &exc);
4015         if (exc != NULL)
4016                 mono_unhandled_exception (exc);
4017
4018         return rval;
4019 }
4020
4021 static void
4022 usage (void)
4023 {
4024         fprintf (stderr,
4025                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4026                  "Usage is: mint [options] executable args...\n\n", VERSION);
4027         fprintf (stderr,
4028                  "Runtime Debugging:\n"
4029 #ifdef DEBUG_INTERP
4030                  "   --debug\n"
4031 #endif
4032                  "   --dieonex\n"
4033                  "   --noptr\t\t\tdon't print pointer addresses in trace output\n"
4034                  "   --opcode-count\n"
4035                  "   --print-vtable\n"
4036                  "   --traceclassinit\n"
4037                  "\n"
4038                  "Development:\n"
4039                  "   --debug method_name\n"
4040                  "   --profile\n"
4041                  "   --trace\n"
4042                  "   --traceops\n"
4043                  "\n"
4044                  "Runtime:\n"
4045                  "   --config filename  load the specified config file instead of the default\n"
4046                  "   --workers n        maximum number of worker threads\n"
4047                 );
4048         exit (1);
4049 }
4050
4051 #ifdef RUN_TEST
4052 static void
4053 test_load_class (MonoImage* image)
4054 {
4055         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
4056         MonoClass *klass;
4057         int i;
4058
4059         for (i = 1; i <= t->rows; ++i) {
4060                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
4061                 mono_class_init (klass);
4062         }
4063 }
4064 #endif
4065
4066 static void
4067 add_signal_handler (int signo, void (*handler)(int))
4068 {
4069 #ifdef PLATFORM_WIN32
4070         signal (signo, handler);
4071 #else
4072         struct sigaction sa;
4073
4074         sa.sa_handler = handler;
4075         sigemptyset (&sa.sa_mask);
4076         sa.sa_flags = 0;
4077
4078         g_assert (sigaction (signo, &sa, NULL) != -1);
4079 #endif
4080 }
4081
4082 static void
4083 segv_handler (int signum)
4084 {
4085         ThreadContext *context = TlsGetValue (thread_context_id);
4086         MonoException *segv_exception;
4087
4088         if (context == NULL)
4089                 return;
4090         segv_exception = mono_get_exception_null_reference ();
4091         segv_exception->message = mono_string_new (mono_domain_get (), "Null Reference (SIGSEGV)");
4092         mono_raise_exception (segv_exception);
4093 }
4094
4095
4096 static void
4097 quit_handler (int signum)
4098 {
4099         ThreadContext *context = TlsGetValue (thread_context_id);
4100         MonoException *quit_exception;
4101
4102         if (context == NULL)
4103                 return;
4104         quit_exception = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
4105         mono_raise_exception (quit_exception);
4106 }
4107
4108 static void
4109 abrt_handler (int signum)
4110 {
4111         ThreadContext *context = TlsGetValue (thread_context_id);
4112         MonoException *abrt_exception;
4113
4114         if (context == NULL)
4115                 return;
4116         abrt_exception = mono_get_exception_execution_engine ("Abort (SIGABRT).");
4117         mono_raise_exception (abrt_exception);
4118 }
4119
4120 static void
4121 thread_abort_handler (int signum)
4122 {
4123         ThreadContext *context = TlsGetValue (thread_context_id);
4124         MonoThread *thread;
4125         MonoException *exc;
4126
4127         if (context == NULL)
4128                 return;
4129
4130         exc = mono_thread_request_interruption (context->managed_code); 
4131         if (exc) mono_raise_exception (exc);
4132 }
4133
4134 static MonoBoolean
4135 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
4136                           MonoReflectionMethod **method, 
4137                           gint32 *iloffset, gint32 *native_offset,
4138                           MonoString **file, gint32 *line, gint32 *column)
4139 {
4140         ThreadContext *context = TlsGetValue (thread_context_id);
4141         MonoInvocation *inv = context->current_frame;
4142         int i;
4143
4144         for (i = 0; inv && i < skip; inv = inv->parent)
4145                 if (inv->runtime_method != NULL)
4146                         ++i;
4147
4148         if (iloffset)
4149                 *iloffset = 0;
4150         if (native_offset)
4151                 *native_offset = 0;
4152         if (method)
4153                 *method = inv == NULL ? NULL : mono_method_get_object (context->domain, inv->runtime_method->method, NULL);
4154         if (line)
4155                 *line = 0;
4156         if (need_file_info) {
4157                 if (column)
4158                         *column = 0;
4159                 if (file)
4160                         *file = mono_string_new (mono_domain_get (), "unknown");
4161         }
4162
4163         return TRUE;
4164 }
4165
4166 static MonoArray *
4167 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
4168 {
4169         MonoDomain *domain = mono_domain_get ();
4170         MonoArray *res;
4171         MonoArray *ta = exc->trace_ips;
4172         int i, len;
4173
4174         if (ta == NULL) {
4175                 /* Exception is not thrown yet */
4176                 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
4177         }
4178         
4179         len = mono_array_length (ta);
4180
4181         res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
4182
4183         for (i = skip; i < len / 2; i++) {
4184                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
4185                 gushort *ip = mono_array_get (ta, gpointer, 2 * i + 1);
4186                 RuntimeMethod *rtm = mono_array_get (ta, gpointer, 2 * i);
4187
4188                 if (rtm != NULL) {
4189                         sf->method = mono_method_get_object (domain, rtm->method, NULL);
4190                         sf->native_offset = ip - rtm->code;
4191                 }
4192
4193 #if 0
4194                 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
4195
4196                 if (need_file_info) {
4197                         gchar *filename;
4198                         
4199                         filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
4200
4201                         sf->filename = filename? mono_string_new (domain, filename): NULL;
4202                         sf->column = 0;
4203
4204                         g_free (filename);
4205                 }
4206 #endif
4207
4208                 mono_array_set (res, gpointer, i, sf);
4209         }
4210
4211         return res;
4212 }
4213
4214 static MonoObject *
4215 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
4216                                                    MonoReflectionMethod *info)
4217 {
4218         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
4219         MonoObject *delegate;
4220
4221         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
4222
4223         delegate = mono_object_new (mono_object_domain (type), delegate_class);
4224
4225         interp_delegate_ctor (mono_object_domain (type), delegate, target, mono_interp_get_runtime_method (info->method));
4226
4227         return delegate;
4228 }
4229
4230
4231 typedef struct
4232 {
4233         MonoDomain *domain;
4234         int enable_debugging;
4235         char *file;
4236         int argc;
4237         char **argv;
4238 } MainThreadArgs;
4239
4240 static void main_thread_handler (gpointer user_data)
4241 {
4242         MainThreadArgs *main_args=(MainThreadArgs *)user_data;
4243         MonoAssembly *assembly;
4244
4245         if (main_args->enable_debugging) {
4246                 mono_debug_init (MONO_DEBUG_FORMAT_MONO);
4247                 mono_debug_init_1 (main_args->domain);
4248         }
4249
4250         assembly = mono_domain_assembly_open (main_args->domain,
4251                                               main_args->file);
4252
4253         if (!assembly){
4254                 fprintf (stderr, "Can not open image %s\n", main_args->file);
4255                 exit (1);
4256         }
4257
4258         if (main_args->enable_debugging)
4259                 mono_debug_init_2 (assembly);
4260
4261 #ifdef RUN_TEST
4262         test_load_class (assembly->image);
4263 #else
4264
4265         ves_exec (main_args->domain, assembly, main_args->argc, main_args->argv);
4266 #endif
4267 }
4268
4269 static void
4270 mono_runtime_install_handlers (void)
4271 {
4272         add_signal_handler (SIGSEGV, segv_handler);
4273         add_signal_handler (SIGINT, quit_handler);
4274         add_signal_handler (SIGABRT, abrt_handler);
4275         add_signal_handler (mono_thread_get_abort_signal (), thread_abort_handler);
4276 }
4277
4278 static void
4279 quit_function (MonoDomain *domain, gpointer user_data)
4280 {
4281         mono_profiler_shutdown ();
4282         
4283         mono_runtime_cleanup (domain);
4284         mono_domain_free (domain, TRUE);
4285
4286 }
4287
4288 void
4289 mono_interp_cleanup(MonoDomain *domain)
4290 {
4291         quit_function (domain, NULL);
4292 }
4293
4294 int
4295 mono_interp_exec(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4296 {
4297         return ves_exec (domain, assembly, argc, argv);
4298 }
4299
4300 MonoDomain *
4301 mono_interp_init(const char *file)
4302 {
4303         MonoDomain *domain;
4304
4305         g_set_prgname (file);
4306         mono_set_rootdir ();
4307         
4308         g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
4309         g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
4310
4311         g_thread_init (NULL);
4312
4313         thread_context_id = TlsAlloc ();
4314         TlsSetValue (thread_context_id, NULL);
4315         InitializeCriticalSection (&runtime_method_lookup_section);
4316         InitializeCriticalSection (&create_method_pointer_mutex);
4317
4318         mono_runtime_install_handlers ();
4319         mono_interp_transform_init ();
4320         mono_install_compile_method (mono_create_method_pointer);
4321         mono_install_runtime_invoke (interp_mono_runtime_invoke);
4322         mono_install_remoting_trampoline (interp_create_remoting_trampoline);
4323         mono_install_trampoline (interp_create_trampoline);
4324
4325         mono_install_handler (interp_ex_handler);
4326         mono_install_stack_walk (interp_walk_stack);
4327         mono_runtime_install_cleanup (quit_function);
4328         abort_requested = mono_thread_interruption_request_flag ();
4329
4330         domain = mono_init (file);
4331 #ifdef __hpux /* generates very big stack frames */
4332         mono_threads_set_default_stacksize(32*1024*1024);
4333 #endif
4334         mono_init_icall ();
4335         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", ves_icall_get_frame_info);
4336         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", ves_icall_get_trace);
4337         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
4338         mono_add_internal_call ("System.Delegate::CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal);
4339
4340         mono_runtime_init (domain, NULL, NULL);
4341
4342         return domain;
4343 }
4344
4345 int 
4346 mono_main (int argc, char *argv [])
4347 {
4348         MonoDomain *domain;
4349         int retval = 0, i;
4350         char *file, *config_file = NULL;
4351         int enable_debugging = FALSE;
4352         MainThreadArgs main_args;
4353         const char *error;
4354
4355         setlocale (LC_ALL, "");
4356         if (argc < 2)
4357                 usage ();
4358
4359         for (i = 1; i < argc && argv [i][0] == '-'; i++){
4360                 if (strcmp (argv [i], "--trace") == 0)
4361                         global_tracing = 1;
4362                 if (strcmp (argv [i], "--noptr") == 0)
4363                         global_no_pointers = 1;
4364                 if (strcmp (argv [i], "--traceops") == 0)
4365                         global_tracing = 2;
4366                 if (strcmp (argv [i], "--traceopt") == 0)
4367                         ++mono_interp_traceopt;
4368                 if (strcmp (argv [i], "--dieonex") == 0) {
4369                         die_on_exception = 1;
4370                         enable_debugging = 1;
4371                 }
4372                 if (strcmp (argv [i], "--print-vtable") == 0)
4373                         mono_print_vtable = TRUE;
4374                 if (strcmp (argv [i], "--profile") == 0)
4375                         mono_profiler_load (NULL);
4376                 if (strcmp (argv [i], "--config") == 0)
4377                         config_file = argv [++i];
4378                 if (strcmp (argv [i], "--workers") == 0) {
4379                         mono_max_worker_threads = atoi (argv [++i]);
4380                         if (mono_max_worker_threads < 1)
4381                                 mono_max_worker_threads = 1;
4382                 }
4383                 if (strcmp (argv [i], "--help") == 0)
4384                         usage ();
4385 #if DEBUG_INTERP
4386                 if (strcmp (argv [i], "--debug") == 0) {
4387                         MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
4388                         if (!desc)
4389                                 g_error ("Invalid method name '%s'", argv [i]);
4390                         db_methods = g_list_append (db_methods, desc);
4391                 }
4392                 if (strcmp (argv [i], "--nested") == 0)
4393                         nested_trace = 1;
4394 #endif
4395         }
4396         
4397         file = argv [i];
4398
4399         if (!file)
4400                 usage ();
4401
4402         domain = mono_interp_init(file);
4403         mono_config_parse (config_file);
4404
4405         error = mono_check_corlib_version ();
4406         if (error) {
4407                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
4408                 fprintf (stderr, "Download a newer corlib at http://www.go-mono.com/daily.\n");
4409                 exit (1);
4410         }
4411
4412         main_args.domain=domain;
4413         main_args.file=file;
4414         main_args.argc=argc-i;
4415         main_args.argv=argv+i;
4416         main_args.enable_debugging=enable_debugging;
4417         
4418         mono_runtime_exec_managed_code (domain, main_thread_handler,
4419                                         &main_args);
4420
4421         quit_function (domain, NULL);
4422
4423         /* Get the return value from System.Environment.ExitCode */
4424         retval=mono_environment_exitcode_get ();
4425
4426 #if COUNT_OPS
4427         for (i = 0; i < 512; i++)
4428                 if (opcode_counts[i] != 0)
4429                         printf("%s %d\n", mono_interp_opname[i], opcode_counts[i]);
4430 #endif
4431         return retval;
4432 }