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