2004-04-29 Bernie Solomon <bernard@ugsolutions.com>
[mono.git] / mono / interpreter / interp.c
1 /*
2  * PLEASE NOTE: This is a research prototype.
3  *
4  *
5  * interp.c: Interpreter for CIL byte codes
6  *
7  * Authors:
8  *   Paolo Molaro (lupus@ximian.com)
9  *   Miguel de Icaza (miguel@ximian.com)
10  *   Dietmar Maurer (dietmar@ximian.com)
11  *
12  * (C) 2001, 2002 Ximian, Inc.
13  */
14 #ifndef __USE_ISOC99
15 #define __USE_ISOC99
16 #endif
17 #include "config.h"
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <setjmp.h>
23 #include <signal.h>
24 #include <math.h>
25 #include <locale.h>
26
27 #include <mono/os/gc_wrapper.h>
28
29 #ifdef HAVE_ALLOCA_H
30 #   include <alloca.h>
31 #else
32 #   ifdef __CYGWIN__
33 #      define alloca __builtin_alloca
34 #   endif
35 #endif
36
37 /* trim excessive headers */
38 #include <mono/metadata/image.h>
39 #include <mono/metadata/assembly.h>
40 #include <mono/metadata/cil-coff.h>
41 #include <mono/metadata/mono-endian.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/tokentype.h>
44 #include <mono/metadata/loader.h>
45 #include <mono/metadata/threads.h>
46 #include <mono/metadata/threadpool.h>
47 #include <mono/metadata/profiler-private.h>
48 #include <mono/metadata/appdomain.h>
49 #include <mono/metadata/reflection.h>
50 #include <mono/metadata/exception.h>
51 #include <mono/metadata/verify.h>
52 #include <mono/metadata/opcodes.h>
53 #include <mono/metadata/debug-helpers.h>
54 #include <mono/metadata/mono-config.h>
55 #include <mono/metadata/marshal.h>
56 #include <mono/metadata/environment.h>
57 #include <mono/metadata/mono-debug.h>
58 #include <mono/os/util.h>
59
60 #include "interp.h"
61 #include "mintops.h"
62 #include "embed.h"
63 #include "hacks.h"
64
65 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
66         a = i,
67
68 enum {
69 #include "mono/cil/opcode.def"
70         CEE_LASTOP
71 };
72 #undef OPDEF
73
74 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
75 #ifdef _WIN32
76 #define isnan _isnan
77 #define finite _finite
78 #endif
79 #ifndef HAVE_FINITE
80 #ifdef HAVE_ISFINITE
81 #define finite isfinite
82 #endif
83 #endif
84
85 /* 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 *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                 g_warning ("caught it");
1069                 if (exc != NULL)
1070                         *exc = (MonoObject *)frame.ex;
1071                 return retval;
1072         }
1073
1074         if (context == NULL) {
1075                 context = &context_struct;
1076                 context_struct.base_frame = &frame;
1077                 context_struct.current_frame = NULL;
1078                 context_struct.env_frame = &frame;
1079                 context_struct.current_env = &env;
1080                 context_struct.search_for_handler = 0;
1081                 context_struct.managed_code = 0;
1082                 context_struct.abort_thread = 0;
1083                 TlsSetValue (thread_context_id, context);
1084         }
1085         else
1086                 old_frame = context->current_frame;
1087
1088         context->domain = mono_domain_get ();
1089
1090         switch (sig->ret->type) {
1091         case MONO_TYPE_VOID:
1092                 break;
1093         case MONO_TYPE_STRING:
1094         case MONO_TYPE_OBJECT:
1095         case MONO_TYPE_CLASS:
1096         case MONO_TYPE_ARRAY:
1097         case MONO_TYPE_SZARRAY:
1098                 isobject = 1;
1099                 break;
1100         case MONO_TYPE_VALUETYPE:
1101                 retval = mono_object_new (context->domain, klass);
1102                 ret = ((char*)retval) + sizeof (MonoObject);
1103                 if (!sig->ret->data.klass->enumtype)
1104                         result.data.vt = ret;
1105                 break;
1106         default:
1107                 retval = mono_object_new (context->domain, klass);
1108                 ret = ((char*)retval) + sizeof (MonoObject);
1109                 break;
1110         }
1111
1112         for (i = 0; i < sig->param_count; ++i) {
1113                 if (sig->params [i]->byref) {
1114                         args [i].data.p = params [i];
1115                         continue;
1116                 }
1117                 type = sig->params [i]->type;
1118 handle_enum:
1119                 switch (type) {
1120                 case MONO_TYPE_U1:
1121                 case MONO_TYPE_I1:
1122                 case MONO_TYPE_BOOLEAN:
1123                         args [i].data.i = *(MonoBoolean*)params [i];
1124                         break;
1125                 case MONO_TYPE_U2:
1126                 case MONO_TYPE_I2:
1127                 case MONO_TYPE_CHAR:
1128                         args [i].data.i = *(gint16*)params [i];
1129                         break;
1130 #if SIZEOF_VOID_P == 4
1131                 case MONO_TYPE_U: /* use VAL_POINTER? */
1132                 case MONO_TYPE_I:
1133 #endif
1134                 case MONO_TYPE_U4:
1135                 case MONO_TYPE_I4:
1136                         args [i].data.i = *(gint32*)params [i];
1137                         break;
1138 #if SIZEOF_VOID_P == 8
1139                 case MONO_TYPE_U:
1140                 case MONO_TYPE_I:
1141 #endif
1142                 case MONO_TYPE_U8:
1143                 case MONO_TYPE_I8:
1144                         args [i].data.l = *(gint64*)params [i];
1145                         break;
1146                 case MONO_TYPE_VALUETYPE:
1147                         if (sig->params [i]->data.klass->enumtype) {
1148                                 type = sig->params [i]->data.klass->enum_basetype->type;
1149                                 goto handle_enum;
1150                         } else {
1151                                 args [i].data.p = params [i];
1152                         }
1153                         break;
1154                 case MONO_TYPE_STRING:
1155                 case MONO_TYPE_CLASS:
1156                 case MONO_TYPE_ARRAY:
1157                 case MONO_TYPE_SZARRAY:
1158                 case MONO_TYPE_OBJECT:
1159                         args [i].data.p = params [i];
1160                         break;
1161                 default:
1162                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1163                 }
1164         }
1165
1166         if (method->klass->valuetype)
1167                 /* Unbox the instance, since valuetype methods expect an interior pointer. */
1168                 obj = mono_object_unbox (obj);
1169
1170         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
1171                 method = mono_marshal_get_native_wrapper (method);
1172         INIT_FRAME(&frame,context->current_frame,obj,args,&result,method);
1173         if (exc)
1174                 frame.invoke_trap = 1;
1175         context->managed_code = 1;
1176         ves_exec_method_with_context (&frame, context);
1177         context->managed_code = 0;
1178         if (context == &context_struct)
1179                 TlsSetValue (thread_context_id, NULL);
1180         else
1181                 context->current_frame = old_frame;
1182         if (frame.ex != NULL) {
1183                 if (exc != NULL) {
1184                         *exc = (MonoObject*) frame.ex;
1185                         return NULL;
1186                 }
1187                 if (context->current_env != NULL) {
1188                         context->env_frame->ex = frame.ex;
1189                         longjmp(*context->current_env, 1);
1190                 }
1191                 else
1192                         printf("dropped exception...\n");
1193         }
1194         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1195                 return NULL;
1196         if (isobject || method->string_ctor)
1197                 return result.data.p;
1198         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1199         return retval;
1200 }
1201
1202 static CRITICAL_SECTION create_method_pointer_mutex;
1203
1204 static MonoGHashTable *method_pointer_hash = NULL;
1205
1206 static void *
1207 mono_create_method_pointer (MonoMethod *method)
1208 {
1209         gpointer addr;
1210         MonoJitInfo *ji;
1211
1212         EnterCriticalSection (&create_method_pointer_mutex);
1213         if (!method_pointer_hash) {
1214                 method_pointer_hash = mono_g_hash_table_new (NULL, NULL);
1215         }
1216         addr = mono_g_hash_table_lookup (method_pointer_hash, method);
1217         if (addr) {
1218                 LeaveCriticalSection (&create_method_pointer_mutex);
1219                 return addr;
1220         }
1221
1222         /*
1223          * If it is a static P/Invoke method, we can just return the pointer
1224          * to the method implementation.
1225          */
1226         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && method->addr) {
1227                 ji = g_new0 (MonoJitInfo, 1);
1228                 ji->method = method;
1229                 ji->code_size = 1;
1230                 ji->code_start = method->addr;
1231
1232                 mono_jit_info_table_add (mono_root_domain, ji);
1233                 
1234                 addr = method->addr;
1235         }               
1236         else
1237                 addr = mono_arch_create_method_pointer (method);
1238
1239         mono_g_hash_table_insert (method_pointer_hash, method, addr);
1240         LeaveCriticalSection (&create_method_pointer_mutex);
1241
1242         return addr;
1243 }
1244
1245 #if COUNT_OPS
1246 static int opcode_counts[512];
1247
1248 #define COUNT_OP(op) opcode_counts[op]++
1249 #else
1250 #define COUNT_OP(op) 
1251 #endif
1252
1253 #if DEBUG_INTERP
1254 #define DUMP_INSTR() \
1255         if (tracing > 1) { \
1256                 char *ins; \
1257                 if (sp > frame->stack) { \
1258                         ins = dump_stack (frame->stack, sp); \
1259                 } else { \
1260                         ins = g_strdup (""); \
1261                 } \
1262                 sp->data.l = 0; \
1263                 output_indent (); \
1264                 g_print ("(%u) ", GetCurrentThreadId()); \
1265                 mono_interp_dis_mintop(rtm->code, ip); \
1266                 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
1267                 g_free (ins); \
1268         }
1269 #else
1270 #define DUMP_INSTR()
1271 #endif
1272
1273 #ifdef __GNUC__
1274 #define USE_COMPUTED_GOTO 1
1275 #endif
1276 #if USE_COMPUTED_GOTO
1277 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
1278 #define MINT_IN_CASE(x) LAB_ ## x:
1279 #if DEBUG_INTERP
1280 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
1281 #else
1282 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
1283 #endif
1284 #define MINT_IN_DEFAULT mint_default:
1285 #else
1286 #define MINT_IN_SWITCH(op) switch (op)
1287 #define MINT_IN_CASE(x) case x:
1288 #define MINT_IN_BREAK break
1289 #define MINT_IN_DEFAULT default:
1290 #endif
1291
1292 static void 
1293 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
1294 {
1295         MonoInvocation child_frame;
1296         GSList *finally_ips = NULL;
1297         const unsigned short *endfinally_ip = NULL;
1298 #if defined(__GNUC__) && defined (i386)
1299         register const unsigned short *ip asm ("%esi");
1300 #else
1301         register const unsigned short *ip;
1302 #endif
1303         register stackval *sp;
1304         RuntimeMethod *rtm;
1305 #if DEBUG_INTERP
1306         gint tracing = global_tracing;
1307         unsigned char *vtalloc;
1308 #endif
1309         int i32;
1310         unsigned char *vt_sp;
1311         char *locals;
1312         MonoObject *o;
1313         MonoClass *c;
1314 #if USE_COMPUTED_GOTO
1315         static void *in_labels[] = {
1316 #define OPDEF(a,b,c,d) \
1317         &&LAB_ ## a,
1318 #include "mintops.def"
1319         0 };
1320 #endif
1321
1322         frame->ex = NULL;
1323         frame->ex_handler = NULL;
1324         frame->ip = NULL;
1325         context->current_frame = frame;
1326
1327         DEBUG_ENTER ();
1328
1329         if (!frame->runtime_method->transformed) {
1330                 context->managed_code = 0;
1331                 frame->ex = mono_interp_transform_method (frame->runtime_method, context);
1332                 context->managed_code = 1;
1333                 if (frame->ex) {
1334                         rtm = NULL;
1335                         ip = NULL;
1336                         goto exit_frame;
1337                 }
1338         }
1339
1340         rtm = frame->runtime_method;
1341         frame->args = alloca (rtm->alloca_size);
1342         sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
1343 #if DEBUG_INTERP
1344         if (tracing > 1)
1345                 memset(sp, 0, rtm->stack_size);
1346 #endif
1347         vt_sp = (char *)sp + rtm->stack_size;
1348 #if DEBUG_INTERP
1349         vtalloc = vt_sp;
1350 #endif
1351         locals = vt_sp + rtm->vt_stack_size;
1352
1353         child_frame.parent = frame;
1354
1355         /* ready to go */
1356         ip = rtm->code;
1357
1358         /*
1359          * using while (ip < end) may result in a 15% performance drop, 
1360          * but it may be useful for debug
1361          */
1362         while (1) {
1363         main_loop:
1364                 /* g_assert (sp >= frame->stack); */
1365                 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
1366                 DUMP_INSTR();
1367                 MINT_IN_SWITCH (*ip) {
1368                 MINT_IN_CASE(MINT_INITLOCALS)
1369                         memset (locals, 0, rtm->locals_size);
1370                         ++ip;
1371                         MINT_IN_BREAK;
1372                 MINT_IN_CASE(MINT_NOP)
1373                         ++ip;
1374                         MINT_IN_BREAK;
1375                 MINT_IN_CASE(MINT_BREAK)
1376                         ++ip;
1377                         G_BREAKPOINT (); /* this is not portable... */
1378                         MINT_IN_BREAK;
1379                 MINT_IN_CASE(MINT_LDNULL) 
1380                         sp->data.p = NULL;
1381                         ++ip;
1382                         ++sp;
1383                         MINT_IN_BREAK;
1384                 MINT_IN_CASE(MINT_VTRESULT) {
1385                         int ret_size = * (guint16 *)(ip + 1);
1386                         char *ret_vt_sp = vt_sp;
1387                         vt_sp -= READ32(ip + 2);
1388                         if (ret_size > 0) {
1389                                 memmove (vt_sp, ret_vt_sp, ret_size);
1390                                 vt_sp += (ret_size + 7) & ~7;
1391                         }
1392                         ip += 4;
1393                         MINT_IN_BREAK;
1394                 }
1395 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
1396                 MINT_IN_CASE(MINT_LDC_I4_M1)
1397                         LDC(-1);
1398                         MINT_IN_BREAK;
1399                 MINT_IN_CASE(MINT_LDC_I4_0)
1400                         LDC(0);
1401                         MINT_IN_BREAK;
1402                 MINT_IN_CASE(MINT_LDC_I4_1)
1403                         LDC(1);
1404                         MINT_IN_BREAK;
1405                 MINT_IN_CASE(MINT_LDC_I4_2)
1406                         LDC(2);
1407                         MINT_IN_BREAK;
1408                 MINT_IN_CASE(MINT_LDC_I4_3)
1409                         LDC(3);
1410                         MINT_IN_BREAK;
1411                 MINT_IN_CASE(MINT_LDC_I4_4)
1412                         LDC(4);
1413                         MINT_IN_BREAK;
1414                 MINT_IN_CASE(MINT_LDC_I4_5)
1415                         LDC(5);
1416                         MINT_IN_BREAK;
1417                 MINT_IN_CASE(MINT_LDC_I4_6)
1418                         LDC(6);
1419                         MINT_IN_BREAK;
1420                 MINT_IN_CASE(MINT_LDC_I4_7)
1421                         LDC(7);
1422                         MINT_IN_BREAK;
1423                 MINT_IN_CASE(MINT_LDC_I4_8)
1424                         LDC(8);
1425                         MINT_IN_BREAK;
1426                 MINT_IN_CASE(MINT_LDC_I4_S) 
1427                         sp->data.i = *(const short *)(ip + 1);
1428                         ip += 2;
1429                         ++sp;
1430                         MINT_IN_BREAK;
1431                 MINT_IN_CASE(MINT_LDC_I4)
1432                         ++ip;
1433                         sp->data.i = READ32 (ip);
1434                         ip += 2;
1435                         ++sp;
1436                         MINT_IN_BREAK;
1437                 MINT_IN_CASE(MINT_LDC_I8)
1438                         ++ip;
1439                         sp->data.l = READ64 (ip);
1440                         ip += 4;
1441                         ++sp;
1442                         MINT_IN_BREAK;
1443                 MINT_IN_CASE(MINT_LDC_R4) {
1444                         guint32 val;
1445                         ++ip;
1446                         val = READ32(ip);
1447                         sp->data.f = * (float *)&val;
1448                         ip += 2;
1449                         ++sp;
1450                         MINT_IN_BREAK;
1451                 }
1452                 MINT_IN_CASE(MINT_LDC_R8) 
1453                         sp->data.l = READ64 (ip + 1); /* note union usage */
1454                         ip += 5;
1455                         ++sp;
1456                         MINT_IN_BREAK;
1457                 MINT_IN_CASE(MINT_DUP) 
1458                         sp [0] = sp[-1];
1459                         ++sp;
1460                         ++ip; 
1461                         MINT_IN_BREAK;
1462                 MINT_IN_CASE(MINT_POP)
1463                         ++ip;
1464                         --sp;
1465                         MINT_IN_BREAK;
1466                 MINT_IN_CASE(MINT_JMP) {
1467                         RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
1468                         if (!new_method->transformed) {
1469                                 frame->ip = ip;
1470                                 frame->ex = mono_interp_transform_method (new_method, context);
1471                                 if (frame->ex)
1472                                         goto exit_frame;
1473                         }
1474                         ip += 2;
1475                         if (new_method->alloca_size > rtm->alloca_size)
1476                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
1477                         rtm = frame->runtime_method = new_method;
1478                         vt_sp = (char *)sp + rtm->stack_size;
1479 #if DEBUG_INTERP
1480                         vtalloc = vt_sp;
1481 #endif
1482                         locals = vt_sp + rtm->vt_stack_size;
1483                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
1484                         MINT_IN_BREAK;
1485                 }
1486                 MINT_IN_CASE(MINT_CALLI) {
1487                         MonoMethodSignature *csignature;
1488                         stackval *endsp = sp;
1489
1490                         frame->ip = ip;
1491                         
1492                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1493                         ip += 2;
1494                         --sp;
1495                         --endsp;
1496                         child_frame.runtime_method = sp->data.p;
1497
1498                         sp->data.p = vt_sp;
1499                         child_frame.retval = sp;
1500                         /* decrement by the actual number of args */
1501                         sp -= csignature->param_count;
1502                         child_frame.stack_args = sp;
1503                         if (csignature->hasthis) {
1504                                 --sp;
1505                                 child_frame.obj = sp->data.p;
1506                         } else {
1507                                 child_frame.obj = NULL;
1508                         }
1509                         if (csignature->hasthis &&
1510                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1511                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1512                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1513                         } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
1514                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1515                                                                 mono_marshal_get_native_wrapper (child_frame.runtime_method->method));
1516
1517                         ves_exec_method_with_context (&child_frame, context);
1518
1519                         context->current_frame = frame;
1520
1521                         if (child_frame.ex) {
1522                                 /*
1523                                  * An exception occurred, need to run finally, fault and catch handlers..
1524                                  */
1525                                 frame->ex = child_frame.ex;
1526                                 goto handle_finally;
1527                         }
1528
1529                         /* need to handle typedbyref ... */
1530                         if (csignature->ret->type != MONO_TYPE_VOID) {
1531                                 *sp = *endsp;
1532                                 sp++;
1533                         }
1534                         MINT_IN_BREAK;
1535                 }
1536                 MINT_IN_CASE(MINT_CALLI_NAT) {
1537                         MonoMethodSignature *csignature;
1538                         stackval *endsp = sp;
1539                         unsigned char *code = NULL;
1540
1541                         frame->ip = ip;
1542                         
1543                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1544                         ip += 2;
1545                         --sp;
1546                         --endsp;
1547                         code = sp->data.p;
1548                         child_frame.runtime_method = NULL;
1549
1550                         sp->data.p = vt_sp;
1551                         child_frame.retval = sp;
1552                         /* decrement by the actual number of args */
1553                         sp -= csignature->param_count;
1554                         child_frame.stack_args = sp;
1555                         if (csignature->hasthis) {
1556                                 --sp;
1557                                 child_frame.obj = sp->data.p;
1558                         } else {
1559                                 child_frame.obj = NULL;
1560                         }
1561                         ves_pinvoke_method (&child_frame, csignature, (MonoFunc) code, FALSE, context);
1562
1563                         context->current_frame = frame;
1564
1565                         if (child_frame.ex) {
1566                                 /*
1567                                  * An exception occurred, need to run finally, fault and catch handlers..
1568                                  */
1569                                 frame->ex = child_frame.ex;
1570                                 if (context->search_for_handler) {
1571                                         context->search_for_handler = 0;
1572                                         goto handle_exception;
1573                                 }
1574                                 goto handle_finally;
1575                         }
1576
1577                         /* need to handle typedbyref ... */
1578                         if (csignature->ret->type != MONO_TYPE_VOID) {
1579                                 *sp = *endsp;
1580                                 sp++;
1581                         }
1582                         MINT_IN_BREAK;
1583                 }
1584                 MINT_IN_CASE(MINT_CALL) {
1585                         stackval *endsp = sp;
1586
1587                         frame->ip = ip;
1588                         
1589                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1590                         ip += 2;
1591                         sp->data.p = vt_sp;
1592                         child_frame.retval = sp;
1593                         /* decrement by the actual number of args */
1594                         sp -= child_frame.runtime_method->param_count;
1595                         child_frame.stack_args = sp;
1596                         if (child_frame.runtime_method->hasthis) {
1597                                 --sp;
1598                                 child_frame.obj = sp->data.p;
1599                         } else {
1600                                 child_frame.obj = NULL;
1601                         }
1602                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
1603                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1604                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1605                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1606                         }
1607                         ves_exec_method_with_context (&child_frame, context);
1608
1609                         context->current_frame = frame;
1610
1611                         if (child_frame.ex) {
1612                                 /*
1613                                  * An exception occurred, need to run finally, fault and catch handlers..
1614                                  */
1615                                 frame->ex = child_frame.ex;
1616                                 goto handle_finally;
1617                         }
1618
1619                         /* need to handle typedbyref ... */
1620                         *sp = *endsp;
1621                         sp++;
1622                         MINT_IN_BREAK;
1623                 }
1624                 MINT_IN_CASE(MINT_VCALL) {
1625                         frame->ip = ip;
1626                         
1627                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1628                         ip += 2;
1629
1630                         sp->data.p = vt_sp;
1631                         child_frame.retval = sp;
1632                         /* decrement by the actual number of args */
1633                         sp -= child_frame.runtime_method->param_count;
1634                         child_frame.stack_args = sp;
1635                         if (child_frame.runtime_method->hasthis) {
1636                                 --sp;
1637                                 child_frame.obj = sp->data.p;
1638                         } else {
1639                                 child_frame.obj = NULL;
1640                         }
1641
1642                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
1643                                         ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
1644                                 child_frame.runtime_method = mono_interp_get_runtime_method (
1645                                                                 mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
1646                         }
1647
1648                         ves_exec_method_with_context (&child_frame, context);
1649
1650                         context->current_frame = frame;
1651
1652                         if (child_frame.ex) {
1653                                 /*
1654                                  * An exception occurred, need to run finally, fault and catch handlers..
1655                                  */
1656                                 frame->ex = child_frame.ex;
1657                                 goto handle_finally;
1658                         }
1659                         MINT_IN_BREAK;
1660                 }
1661                 MINT_IN_CASE(MINT_CALLVIRT) {
1662                         stackval *endsp = sp;
1663                         MonoObject *this_arg;
1664                         guint32 token;
1665
1666                         frame->ip = ip;
1667                         
1668                         token = * (unsigned short *)(ip + 1);
1669                         ip += 2;
1670                         child_frame.runtime_method = rtm->data_items [token];
1671                         sp->data.p = vt_sp;
1672                         child_frame.retval = sp;
1673
1674                         /* decrement by the actual number of args */
1675                         sp -= child_frame.runtime_method->param_count;
1676                         child_frame.stack_args = sp;
1677                         --sp;
1678                         child_frame.obj = this_arg = sp->data.p;
1679                         if (!this_arg)
1680                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
1681                         child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
1682
1683                         if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
1684                                 child_frame.obj = (char *)this_arg + sizeof(MonoObject);
1685                         }
1686
1687                         ves_exec_method_with_context (&child_frame, context);
1688
1689                         context->current_frame = frame;
1690
1691                         if (child_frame.ex) {
1692                                 /*
1693                                  * An exception occurred, need to run finally, fault and catch handlers..
1694                                  */
1695                                 frame->ex = child_frame.ex;
1696                                 if (context->search_for_handler) {
1697                                         context->search_for_handler = 0;
1698                                         goto handle_exception;
1699                                 }
1700                                 goto handle_finally;
1701                         }
1702
1703                         /* need to handle typedbyref ... */
1704                         *sp = *endsp;
1705                         sp++;
1706                         MINT_IN_BREAK;
1707                 }
1708                 MINT_IN_CASE(MINT_VCALLVIRT) {
1709                         MonoObject *this_arg;
1710                         guint32 token;
1711
1712                         frame->ip = ip;
1713                         
1714                         token = * (unsigned short *)(ip + 1);
1715                         ip += 2;
1716                         child_frame.runtime_method = rtm->data_items [token];
1717                         sp->data.p = vt_sp;
1718                         child_frame.retval = sp;
1719
1720                         /* decrement by the actual number of args */
1721                         sp -= child_frame.runtime_method->param_count;
1722                         child_frame.stack_args = sp;
1723                         --sp;
1724                         child_frame.obj = this_arg = sp->data.p;
1725                         if (!this_arg)
1726                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
1727                         child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
1728
1729                         if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
1730                                 child_frame.obj = (char *)this_arg + sizeof(MonoObject);
1731                         }
1732
1733                         ves_exec_method_with_context (&child_frame, context);
1734
1735                         context->current_frame = frame;
1736
1737                         if (child_frame.ex) {
1738                                 /*
1739                                  * An exception occurred, need to run finally, fault and catch handlers..
1740                                  */
1741                                 frame->ex = child_frame.ex;
1742                                 if (context->search_for_handler) {
1743                                         context->search_for_handler = 0;
1744                                         goto handle_exception;
1745                                 }
1746                                 goto handle_finally;
1747                         }
1748                         MINT_IN_BREAK;
1749                 }
1750                 MINT_IN_CASE(MINT_CALLINT)
1751                         ves_pinvoke_method (frame, frame->runtime_method->method->signature, frame->runtime_method->method->addr, 
1752                                     frame->runtime_method->method->string_ctor, context);
1753                         if (frame->ex) {
1754                                 rtm = NULL;
1755                                 goto handle_exception;
1756                         }
1757                         goto exit_frame;
1758                 MINT_IN_CASE(MINT_CALLRUN)
1759                         ves_runtime_method (frame, context);
1760                         if (frame->ex) {
1761                                 rtm = NULL;
1762                                 goto handle_exception;
1763                         }
1764                         goto exit_frame;
1765                 MINT_IN_CASE(MINT_RET)
1766                         --sp;
1767                         *frame->retval = *sp;
1768                         if (sp > frame->stack)
1769                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
1770                         goto exit_frame;
1771                 MINT_IN_CASE(MINT_RET_VOID)
1772                         if (sp > frame->stack)
1773                                 g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
1774                         goto exit_frame;
1775                 MINT_IN_CASE(MINT_RET_VT)
1776                         i32 = READ32(ip + 1);
1777                         --sp;
1778                         memcpy(frame->retval->data.p, sp->data.p, i32);
1779                         if (sp > frame->stack)
1780                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
1781                         goto exit_frame;
1782                 MINT_IN_CASE(MINT_BR_S)
1783                         ip += (short) *(ip + 1);
1784                         MINT_IN_BREAK;
1785                 MINT_IN_CASE(MINT_BR)
1786                         ip += (gint32) READ32(ip + 1);
1787                         MINT_IN_BREAK;
1788 #define ZEROP_S(datamem, op) \
1789         --sp; \
1790         if (sp->data.datamem op 0) \
1791                 ip += * (gint16 *)(ip + 1); \
1792         else \
1793                 ip += 2;
1794
1795 #define ZEROP(datamem, op) \
1796         --sp; \
1797         if (sp->data.datamem op 0) \
1798                 ip += READ32(ip + 1); \
1799         else \
1800                 ip += 3;
1801
1802                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
1803                         ZEROP_S(i, ==);
1804                         MINT_IN_BREAK;
1805                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
1806                         ZEROP_S(l, ==);
1807                         MINT_IN_BREAK;
1808                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
1809                         ZEROP_S(f, ==);
1810                         MINT_IN_BREAK;
1811                 MINT_IN_CASE(MINT_BRFALSE_I4)
1812                         ZEROP(i, ==);
1813                         MINT_IN_BREAK;
1814                 MINT_IN_CASE(MINT_BRFALSE_I8)
1815                         ZEROP(l, ==);
1816                         MINT_IN_BREAK;
1817                 MINT_IN_CASE(MINT_BRFALSE_R8)
1818                         ZEROP_S(f, ==);
1819                         MINT_IN_BREAK;
1820                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
1821                         ZEROP_S(i, !=);
1822                         MINT_IN_BREAK;
1823                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
1824                         ZEROP_S(l, !=);
1825                         MINT_IN_BREAK;
1826                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
1827                         ZEROP_S(f, !=);
1828                         MINT_IN_BREAK;
1829                 MINT_IN_CASE(MINT_BRTRUE_I4)
1830                         ZEROP(i, !=);
1831                         MINT_IN_BREAK;
1832                 MINT_IN_CASE(MINT_BRTRUE_I8)
1833                         ZEROP(l, !=);
1834                         MINT_IN_BREAK;
1835                 MINT_IN_CASE(MINT_BRTRUE_R8)
1836                         ZEROP(f, !=);
1837                         MINT_IN_BREAK;
1838 #define CONDBR_S(cond) \
1839         sp -= 2; \
1840         if (cond) \
1841                 ip += * (gint16 *)(ip + 1); \
1842         else \
1843                 ip += 2;
1844 #define BRELOP_S(datamem, op) \
1845         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
1846
1847 #define CONDBR(cond) \
1848         sp -= 2; \
1849         if (cond) \
1850                 ip += READ32(ip + 1); \
1851         else \
1852                 ip += 3;
1853
1854 #define BRELOP(datamem, op) \
1855         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
1856
1857                 MINT_IN_CASE(MINT_BEQ_I4_S)
1858                         BRELOP_S(i, ==)
1859                         MINT_IN_BREAK;
1860                 MINT_IN_CASE(MINT_BEQ_I8_S)
1861                         BRELOP_S(l, ==)
1862                         MINT_IN_BREAK;
1863                 MINT_IN_CASE(MINT_BEQ_R8_S)
1864                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
1865                         MINT_IN_BREAK;
1866                 MINT_IN_CASE(MINT_BEQ_I4)
1867                         BRELOP(i, ==)
1868                         MINT_IN_BREAK;
1869                 MINT_IN_CASE(MINT_BEQ_I8)
1870                         BRELOP(l, ==)
1871                         MINT_IN_BREAK;
1872                 MINT_IN_CASE(MINT_BEQ_R8)
1873                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
1874                         MINT_IN_BREAK;
1875                 MINT_IN_CASE(MINT_BGE_I4_S)
1876                         BRELOP_S(i, >=)
1877                         MINT_IN_BREAK;
1878                 MINT_IN_CASE(MINT_BGE_I8_S)
1879                         BRELOP_S(l, >=)
1880                         MINT_IN_BREAK;
1881                 MINT_IN_CASE(MINT_BGE_R8_S)
1882                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
1883                         MINT_IN_BREAK;
1884                 MINT_IN_CASE(MINT_BGE_I4)
1885                         BRELOP(i, >=)
1886                         MINT_IN_BREAK;
1887                 MINT_IN_CASE(MINT_BGE_I8)
1888                         BRELOP(l, >=)
1889                         MINT_IN_BREAK;
1890                 MINT_IN_CASE(MINT_BGE_R8)
1891                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
1892                         MINT_IN_BREAK;
1893                 MINT_IN_CASE(MINT_BGT_I4_S)
1894                         BRELOP_S(i, >)
1895                         MINT_IN_BREAK;
1896                 MINT_IN_CASE(MINT_BGT_I8_S)
1897                         BRELOP_S(l, >)
1898                         MINT_IN_BREAK;
1899                 MINT_IN_CASE(MINT_BGT_R8_S)
1900                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
1901                         MINT_IN_BREAK;
1902                 MINT_IN_CASE(MINT_BGT_I4)
1903                         BRELOP(i, >)
1904                         MINT_IN_BREAK;
1905                 MINT_IN_CASE(MINT_BGT_I8)
1906                         BRELOP(l, >)
1907                         MINT_IN_BREAK;
1908                 MINT_IN_CASE(MINT_BGT_R8)
1909                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
1910                         MINT_IN_BREAK;
1911                 MINT_IN_CASE(MINT_BLT_I4_S)
1912                         BRELOP_S(i, <)
1913                         MINT_IN_BREAK;
1914                 MINT_IN_CASE(MINT_BLT_I8_S)
1915                         BRELOP_S(l, <)
1916                         MINT_IN_BREAK;
1917                 MINT_IN_CASE(MINT_BLT_R8_S)
1918                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
1919                         MINT_IN_BREAK;
1920                 MINT_IN_CASE(MINT_BLT_I4)
1921                         BRELOP(i, <)
1922                         MINT_IN_BREAK;
1923                 MINT_IN_CASE(MINT_BLT_I8)
1924                         BRELOP(l, <)
1925                         MINT_IN_BREAK;
1926                 MINT_IN_CASE(MINT_BLT_R8)
1927                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
1928                         MINT_IN_BREAK;
1929                 MINT_IN_CASE(MINT_BLE_I4_S)
1930                         BRELOP_S(i, <=)
1931                         MINT_IN_BREAK;
1932                 MINT_IN_CASE(MINT_BLE_I8_S)
1933                         BRELOP_S(l, <=)
1934                         MINT_IN_BREAK;
1935                 MINT_IN_CASE(MINT_BLE_R8_S)
1936                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
1937                         MINT_IN_BREAK;
1938                 MINT_IN_CASE(MINT_BLE_I4)
1939                         BRELOP(i, <=)
1940                         MINT_IN_BREAK;
1941                 MINT_IN_CASE(MINT_BLE_I8)
1942                         BRELOP(l, <=)
1943                         MINT_IN_BREAK;
1944                 MINT_IN_CASE(MINT_BLE_R8)
1945                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
1946                         MINT_IN_BREAK;
1947                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
1948                         BRELOP_S(i, !=)
1949                         MINT_IN_BREAK;
1950                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
1951                         BRELOP_S(l, !=)
1952                         MINT_IN_BREAK;
1953                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
1954                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
1955                         MINT_IN_BREAK;
1956                 MINT_IN_CASE(MINT_BNE_UN_I4)
1957                         BRELOP(i, !=)
1958                         MINT_IN_BREAK;
1959                 MINT_IN_CASE(MINT_BNE_UN_I8)
1960                         BRELOP(l, !=)
1961                         MINT_IN_BREAK;
1962                 MINT_IN_CASE(MINT_BNE_UN_R8)
1963                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
1964                         MINT_IN_BREAK;
1965
1966 #define BRELOP_S_CAST(datamem, op, type) \
1967         sp -= 2; \
1968         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
1969                 ip += * (gint16 *)(ip + 1); \
1970         else \
1971                 ip += 2;
1972
1973 #define BRELOP_CAST(datamem, op, type) \
1974         sp -= 2; \
1975         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
1976                 ip += READ32(ip + 1); \
1977         else \
1978                 ip += 3;
1979
1980                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
1981                         BRELOP_S_CAST(i, >=, guint32);
1982                         MINT_IN_BREAK;
1983                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
1984                         BRELOP_S_CAST(l, >=, guint64);
1985                         MINT_IN_BREAK;
1986                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
1987                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
1988                         MINT_IN_BREAK;
1989                 MINT_IN_CASE(MINT_BGE_UN_I4)
1990                         BRELOP_CAST(i, >=, guint32);
1991                         MINT_IN_BREAK;
1992                 MINT_IN_CASE(MINT_BGE_UN_I8)
1993                         BRELOP_CAST(l, >=, guint64);
1994                         MINT_IN_BREAK;
1995                 MINT_IN_CASE(MINT_BGE_UN_R8)
1996                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
1997                         MINT_IN_BREAK;
1998                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
1999                         BRELOP_S_CAST(i, >, guint32);
2000                         MINT_IN_BREAK;
2001                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
2002                         BRELOP_S_CAST(l, >, guint64);
2003                         MINT_IN_BREAK;
2004                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
2005                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2006                         MINT_IN_BREAK;
2007                 MINT_IN_CASE(MINT_BGT_UN_I4)
2008                         BRELOP_CAST(i, >, guint32);
2009                         MINT_IN_BREAK;
2010                 MINT_IN_CASE(MINT_BGT_UN_I8)
2011                         BRELOP_CAST(l, >, guint64);
2012                         MINT_IN_BREAK;
2013                 MINT_IN_CASE(MINT_BGT_UN_R8)
2014                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2015                         MINT_IN_BREAK;
2016                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
2017                         BRELOP_S_CAST(i, <=, guint32);
2018                         MINT_IN_BREAK;
2019                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
2020                         BRELOP_S_CAST(l, <=, guint64);
2021                         MINT_IN_BREAK;
2022                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
2023                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2024                         MINT_IN_BREAK;
2025                 MINT_IN_CASE(MINT_BLE_UN_I4)
2026                         BRELOP_CAST(i, <=, guint32);
2027                         MINT_IN_BREAK;
2028                 MINT_IN_CASE(MINT_BLE_UN_I8)
2029                         BRELOP_CAST(l, <=, guint64);
2030                         MINT_IN_BREAK;
2031                 MINT_IN_CASE(MINT_BLE_UN_R8)
2032                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2033                         MINT_IN_BREAK;
2034                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
2035                         BRELOP_S_CAST(i, <, guint32);
2036                         MINT_IN_BREAK;
2037                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
2038                         BRELOP_S_CAST(l, <, guint64);
2039                         MINT_IN_BREAK;
2040                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
2041                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2042                         MINT_IN_BREAK;
2043                 MINT_IN_CASE(MINT_BLT_UN_I4)
2044                         BRELOP_CAST(i, <, guint32);
2045                         MINT_IN_BREAK;
2046                 MINT_IN_CASE(MINT_BLT_UN_I8)
2047                         BRELOP_CAST(l, <, guint64);
2048                         MINT_IN_BREAK;
2049                 MINT_IN_CASE(MINT_BLT_UN_R8)
2050                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2051                         MINT_IN_BREAK;
2052                 MINT_IN_CASE(MINT_SWITCH) {
2053                         guint32 n;
2054                         const unsigned short *st;
2055                         ++ip;
2056                         n = READ32 (ip);
2057                         ip += 2;
2058                         st = ip + 2 * n;
2059                         --sp;
2060                         if ((guint32)sp->data.i < n) {
2061                                 gint offset;
2062                                 ip += 2 * (guint32)sp->data.i;
2063                                 offset = READ32 (ip);
2064                                 ip = st + offset;
2065                         } else {
2066                                 ip = st;
2067                         }
2068                         MINT_IN_BREAK;
2069                 }
2070                 MINT_IN_CASE(MINT_LDIND_I1)
2071                         ++ip;
2072                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
2073                         MINT_IN_BREAK;
2074                 MINT_IN_CASE(MINT_LDIND_U1)
2075                         ++ip;
2076                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
2077                         MINT_IN_BREAK;
2078                 MINT_IN_CASE(MINT_LDIND_I2)
2079                         ++ip;
2080                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
2081                         MINT_IN_BREAK;
2082                 MINT_IN_CASE(MINT_LDIND_U2)
2083                         ++ip;
2084                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
2085                         MINT_IN_BREAK;
2086                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
2087                 MINT_IN_CASE(MINT_LDIND_U4)
2088                         ++ip;
2089                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
2090                         MINT_IN_BREAK;
2091                 MINT_IN_CASE(MINT_LDIND_I8)
2092                         ++ip;
2093                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
2094                         MINT_IN_BREAK;
2095                 MINT_IN_CASE(MINT_LDIND_I)
2096                         ++ip;
2097                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2098                         MINT_IN_BREAK;
2099                 MINT_IN_CASE(MINT_LDIND_R4)
2100                         ++ip;
2101                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
2102                         MINT_IN_BREAK;
2103                 MINT_IN_CASE(MINT_LDIND_R8)
2104                         ++ip;
2105                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
2106                         MINT_IN_BREAK;
2107                 MINT_IN_CASE(MINT_LDIND_REF)
2108                         ++ip;
2109                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2110                         MINT_IN_BREAK;
2111                 MINT_IN_CASE(MINT_STIND_REF) 
2112                         ++ip;
2113                         sp -= 2;
2114                         * (gpointer *) sp->data.p = sp[1].data.p;
2115                         MINT_IN_BREAK;
2116                 MINT_IN_CASE(MINT_STIND_I1)
2117                         ++ip;
2118                         sp -= 2;
2119                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
2120                         MINT_IN_BREAK;
2121                 MINT_IN_CASE(MINT_STIND_I2)
2122                         ++ip;
2123                         sp -= 2;
2124                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
2125                         MINT_IN_BREAK;
2126                 MINT_IN_CASE(MINT_STIND_I4)
2127                         ++ip;
2128                         sp -= 2;
2129                         * (gint32 *) sp->data.p = sp[1].data.i;
2130                         MINT_IN_BREAK;
2131                 MINT_IN_CASE(MINT_STIND_I)
2132                         ++ip;
2133                         sp -= 2;
2134                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
2135                         MINT_IN_BREAK;
2136                 MINT_IN_CASE(MINT_STIND_I8)
2137                         ++ip;
2138                         sp -= 2;
2139                         * (gint64 *) sp->data.p = sp[1].data.l;
2140                         MINT_IN_BREAK;
2141                 MINT_IN_CASE(MINT_STIND_R4)
2142                         ++ip;
2143                         sp -= 2;
2144                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
2145                         MINT_IN_BREAK;
2146                 MINT_IN_CASE(MINT_STIND_R8)
2147                         ++ip;
2148                         sp -= 2;
2149                         * (double *) sp->data.p = sp[1].data.f;
2150                         MINT_IN_BREAK;
2151 #define BINOP(datamem, op) \
2152         --sp; \
2153         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
2154         ++ip;
2155                 MINT_IN_CASE(MINT_ADD_I4)
2156                         BINOP(i, +);
2157                         MINT_IN_BREAK;
2158                 MINT_IN_CASE(MINT_ADD_I8)
2159                         BINOP(l, +);
2160                         MINT_IN_BREAK;
2161                 MINT_IN_CASE(MINT_ADD_R8)
2162                         BINOP(f, +);
2163                         MINT_IN_BREAK;
2164                 MINT_IN_CASE(MINT_ADD1_I4)
2165                         ++sp [-1].data.i;
2166                         ++ip;
2167                         MINT_IN_BREAK;
2168                 MINT_IN_CASE(MINT_SUB_I4)
2169                         BINOP(i, -);
2170                         MINT_IN_BREAK;
2171                 MINT_IN_CASE(MINT_SUB_I8)
2172                         BINOP(l, -);
2173                         MINT_IN_BREAK;
2174                 MINT_IN_CASE(MINT_SUB_R8)
2175                         BINOP(f, -);
2176                         MINT_IN_BREAK;
2177                 MINT_IN_CASE(MINT_SUB1_I4)
2178                         --sp [-1].data.i;
2179                         ++ip;
2180                         MINT_IN_BREAK;
2181                 MINT_IN_CASE(MINT_MUL_I4)
2182                         BINOP(i, *);
2183                         MINT_IN_BREAK;
2184                 MINT_IN_CASE(MINT_MUL_I8)
2185                         BINOP(l, *);
2186                         MINT_IN_BREAK;
2187                 MINT_IN_CASE(MINT_MUL_R8)
2188                         BINOP(f, *);
2189                         MINT_IN_BREAK;
2190                 MINT_IN_CASE(MINT_DIV_I4)
2191                         if (sp [-1].data.i == 0)
2192                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2193                         BINOP(i, /);
2194                         MINT_IN_BREAK;
2195                 MINT_IN_CASE(MINT_DIV_I8)
2196                         if (sp [-1].data.l == 0)
2197                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2198                         BINOP(l, /);
2199                         MINT_IN_BREAK;
2200                 MINT_IN_CASE(MINT_DIV_R8)
2201                         BINOP(f, /);
2202                         MINT_IN_BREAK;
2203
2204 #define BINOP_CAST(datamem, op, type) \
2205         --sp; \
2206         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
2207         ++ip;
2208                 MINT_IN_CASE(MINT_DIV_UN_I4)
2209                         if (sp [-1].data.i == 0)
2210                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2211                         BINOP_CAST(i, /, guint32);
2212                         MINT_IN_BREAK;
2213                 MINT_IN_CASE(MINT_DIV_UN_I8)
2214                         if (sp [-1].data.l == 0)
2215                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2216                         BINOP_CAST(l, /, guint64);
2217                         MINT_IN_BREAK;
2218                 MINT_IN_CASE(MINT_REM_I4)
2219                         if (sp [-1].data.i == 0)
2220                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2221                         BINOP(i, %);
2222                         MINT_IN_BREAK;
2223                 MINT_IN_CASE(MINT_REM_I8)
2224                         if (sp [-1].data.l == 0)
2225                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2226                         BINOP(l, %);
2227                         MINT_IN_BREAK;
2228                 MINT_IN_CASE(MINT_REM_R8)
2229                         /* FIXME: what do we actually do here? */
2230                         --sp;
2231                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
2232                         ++ip;
2233                         MINT_IN_BREAK;
2234                 MINT_IN_CASE(MINT_REM_UN_I4)
2235                         if (sp [-1].data.i == 0)
2236                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2237                         BINOP_CAST(i, %, guint32);
2238                         MINT_IN_BREAK;
2239                 MINT_IN_CASE(MINT_REM_UN_I8)
2240                         if (sp [-1].data.l == 0)
2241                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2242                         BINOP_CAST(l, %, guint64);
2243                         MINT_IN_BREAK;
2244                 MINT_IN_CASE(MINT_AND_I4)
2245                         BINOP(i, &);
2246                         MINT_IN_BREAK;
2247                 MINT_IN_CASE(MINT_AND_I8)
2248                         BINOP(l, &);
2249                         MINT_IN_BREAK;
2250                 MINT_IN_CASE(MINT_OR_I4)
2251                         BINOP(i, |);
2252                         MINT_IN_BREAK;
2253                 MINT_IN_CASE(MINT_OR_I8)
2254                         BINOP(l, |);
2255                         MINT_IN_BREAK;
2256                 MINT_IN_CASE(MINT_XOR_I4)
2257                         BINOP(i, ^);
2258                         MINT_IN_BREAK;
2259                 MINT_IN_CASE(MINT_XOR_I8)
2260                         BINOP(l, ^);
2261                         MINT_IN_BREAK;
2262
2263 #define SHIFTOP(datamem, op) \
2264         --sp; \
2265         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
2266         ++ip;
2267
2268                 MINT_IN_CASE(MINT_SHL_I4)
2269                         SHIFTOP(i, <<);
2270                         MINT_IN_BREAK;
2271                 MINT_IN_CASE(MINT_SHL_I8)
2272                         SHIFTOP(l, <<);
2273                         MINT_IN_BREAK;
2274                 MINT_IN_CASE(MINT_SHR_I4)
2275                         SHIFTOP(i, >>);
2276                         MINT_IN_BREAK;
2277                 MINT_IN_CASE(MINT_SHR_I8)
2278                         SHIFTOP(l, >>);
2279                         MINT_IN_BREAK;
2280                 MINT_IN_CASE(MINT_SHR_UN_I4)
2281                         --sp;
2282                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
2283                         ++ip;
2284                         MINT_IN_BREAK;
2285                 MINT_IN_CASE(MINT_SHR_UN_I8)
2286                         --sp;
2287                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
2288                         ++ip;
2289                         MINT_IN_BREAK;
2290                 MINT_IN_CASE(MINT_NEG_I4)
2291                         sp [-1].data.i = - sp [-1].data.i;
2292                         ++ip;
2293                         MINT_IN_BREAK;
2294                 MINT_IN_CASE(MINT_NEG_I8)
2295                         sp [-1].data.l = - sp [-1].data.l;
2296                         ++ip;
2297                         MINT_IN_BREAK;
2298                 MINT_IN_CASE(MINT_NEG_R8)
2299                         sp [-1].data.f = - sp [-1].data.f;
2300                         ++ip;
2301                         MINT_IN_BREAK;
2302                 MINT_IN_CASE(MINT_NOT_I4)
2303                         sp [-1].data.i = ~ sp [-1].data.i;
2304                         ++ip;
2305                         MINT_IN_BREAK;
2306                 MINT_IN_CASE(MINT_NOT_I8)
2307                         sp [-1].data.l = ~ sp [-1].data.l;
2308                         ++ip;
2309                         MINT_IN_BREAK;
2310                 MINT_IN_CASE(MINT_CONV_I1_I4)
2311                         sp [-1].data.i = (gint8)sp [-1].data.i;
2312                         ++ip;
2313                         MINT_IN_BREAK;
2314                 MINT_IN_CASE(MINT_CONV_I1_I8)
2315                         sp [-1].data.i = (gint8)sp [-1].data.l;
2316                         ++ip;
2317                         MINT_IN_BREAK;
2318                 MINT_IN_CASE(MINT_CONV_I1_R8)
2319                         sp [-1].data.i = (gint8)sp [-1].data.f;
2320                         ++ip;
2321                         MINT_IN_BREAK;
2322                 MINT_IN_CASE(MINT_CONV_U1_I4)
2323                         sp [-1].data.i = (guint8)sp [-1].data.i;
2324                         ++ip;
2325                         MINT_IN_BREAK;
2326                 MINT_IN_CASE(MINT_CONV_U1_I8)
2327                         sp [-1].data.i = (guint8)sp [-1].data.l;
2328                         ++ip;
2329                         MINT_IN_BREAK;
2330                 MINT_IN_CASE(MINT_CONV_U1_R8)
2331                         sp [-1].data.i = (guint8)sp [-1].data.f;
2332                         ++ip;
2333                         MINT_IN_BREAK;
2334                 MINT_IN_CASE(MINT_CONV_I2_I4)
2335                         sp [-1].data.i = (gint16)sp [-1].data.i;
2336                         ++ip;
2337                         MINT_IN_BREAK;
2338                 MINT_IN_CASE(MINT_CONV_I2_I8)
2339                         sp [-1].data.i = (gint16)sp [-1].data.l;
2340                         ++ip;
2341                         MINT_IN_BREAK;
2342                 MINT_IN_CASE(MINT_CONV_I2_R8)
2343                         sp [-1].data.i = (gint16)sp [-1].data.f;
2344                         ++ip;
2345                         MINT_IN_BREAK;
2346                 MINT_IN_CASE(MINT_CONV_U2_I4)
2347                         sp [-1].data.i = (guint16)sp [-1].data.i;
2348                         ++ip;
2349                         MINT_IN_BREAK;
2350                 MINT_IN_CASE(MINT_CONV_U2_I8)
2351                         sp [-1].data.i = (guint16)sp [-1].data.l;
2352                         ++ip;
2353                         MINT_IN_BREAK;
2354                 MINT_IN_CASE(MINT_CONV_U2_R8)
2355                         sp [-1].data.i = (guint16)sp [-1].data.f;
2356                         ++ip;
2357                         MINT_IN_BREAK;
2358                 MINT_IN_CASE(MINT_CONV_I4_R8)
2359                         sp [-1].data.i = (gint32)sp [-1].data.f;
2360                         ++ip;
2361                         MINT_IN_BREAK;
2362                 MINT_IN_CASE(MINT_CONV_U4_I8)
2363                 MINT_IN_CASE(MINT_CONV_I4_I8)
2364                         sp [-1].data.i = (gint32)sp [-1].data.l;
2365                         ++ip;
2366                         MINT_IN_BREAK;
2367                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
2368                         sp [-2].data.i = (gint32)sp [-2].data.l;
2369                         ++ip;
2370                         MINT_IN_BREAK;
2371                 MINT_IN_CASE(MINT_CONV_U4_R8)
2372                         sp [-1].data.i = (guint32)sp [-1].data.f;
2373                         ++ip;
2374                         MINT_IN_BREAK;
2375                 MINT_IN_CASE(MINT_CONV_I8_I4)
2376                         sp [-1].data.l = sp [-1].data.i;
2377                         ++ip;
2378                         MINT_IN_BREAK;
2379                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
2380                         sp [-2].data.l = sp [-2].data.i;
2381                         ++ip;
2382                         MINT_IN_BREAK;
2383                 MINT_IN_CASE(MINT_CONV_I8_U4)
2384                         sp [-1].data.l = (guint32)sp [-1].data.i;
2385                         ++ip;
2386                         MINT_IN_BREAK;
2387                 MINT_IN_CASE(MINT_CONV_I8_R8)
2388                         sp [-1].data.l = (gint64)sp [-1].data.f;
2389                         ++ip;
2390                         MINT_IN_BREAK;
2391                 MINT_IN_CASE(MINT_CONV_R4_I4)
2392                         sp [-1].data.f = (float)sp [-1].data.i;
2393                         ++ip;
2394                         MINT_IN_BREAK;
2395                 MINT_IN_CASE(MINT_CONV_R4_I8)
2396                         sp [-1].data.f = (float)sp [-1].data.l;
2397                         ++ip;
2398                         MINT_IN_BREAK;
2399                 MINT_IN_CASE(MINT_CONV_R4_R8)
2400                         sp [-1].data.f = (float)sp [-1].data.f;
2401                         ++ip;
2402                         MINT_IN_BREAK;
2403                 MINT_IN_CASE(MINT_CONV_R8_I4)
2404                         sp [-1].data.f = (double)sp [-1].data.i;
2405                         ++ip;
2406                         MINT_IN_BREAK;
2407                 MINT_IN_CASE(MINT_CONV_R8_I8)
2408                         sp [-1].data.f = (double)sp [-1].data.l;
2409                         ++ip;
2410                         MINT_IN_BREAK;
2411                 MINT_IN_CASE(MINT_CONV_U8_I4)
2412                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
2413                         ++ip;
2414                         MINT_IN_BREAK;
2415                 MINT_IN_CASE(MINT_CONV_U8_R8)
2416                         sp [-1].data.l = (guint64)sp [-1].data.f;
2417                         ++ip;
2418                         MINT_IN_BREAK;
2419 #if 0
2420                 MINT_IN_CASE(MINT_CPOBJ) {
2421                         MonoClass *vtklass;
2422                         ++ip;
2423                         vtklass = rtm->data_items[READ32 (ip)];
2424                         ip += 2;
2425                         sp -= 2;
2426                         memcpy (sp [0].data.p, sp [1].data.p, mono_class_value_size (vtklass, NULL));
2427                         MINT_IN_BREAK;
2428                 }
2429 #endif
2430                 MINT_IN_CASE(MINT_LDOBJ) {
2431                         int size;
2432                         void *p;
2433                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2434                         ip += 2;
2435                         if (c->byval_arg.type != MONO_TYPE_VALUETYPE || c->byval_arg.data.klass->enumtype) {
2436                                 p = sp [-1].data.p;
2437                                 stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
2438                         } else {
2439                                 size = mono_class_value_size (c, NULL);
2440                                 p = sp [-1].data.p;
2441                                 sp [-1].data.p = vt_sp;
2442                                 memcpy(vt_sp, p, size);
2443                                 vt_sp += (size + 7) & ~7;
2444                         }
2445                         MINT_IN_BREAK;
2446                 }
2447                 MINT_IN_CASE(MINT_LDSTR)
2448                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
2449                         ++sp;
2450                         ip += 2;
2451                         MINT_IN_BREAK;
2452                 MINT_IN_CASE(MINT_NEWOBJ) {
2453                         MonoClass *newobj_class;
2454                         MonoMethodSignature *csig;
2455                         stackval valuetype_this;
2456                         guint32 token;
2457                         stackval retval;
2458
2459                         frame->ip = ip;
2460
2461                         token = * (guint16 *)(ip + 1);
2462                         ip += 2;
2463
2464                         child_frame.runtime_method = rtm->data_items [token];
2465                         csig = child_frame.runtime_method->method->signature;
2466                         newobj_class = child_frame.runtime_method->method->klass;
2467                         /*if (profiling_classes) {
2468                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
2469                                 count++;
2470                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
2471                         }*/
2472                                 
2473
2474                         if (newobj_class->parent == mono_defaults.array_class) {
2475                                 sp -= csig->param_count;
2476                                 o = ves_array_create (context->domain, newobj_class, csig, sp);
2477                                 goto array_constructed;
2478                         }
2479
2480                         /*
2481                          * First arg is the object.
2482                          */
2483                         if (newobj_class->valuetype) {
2484                                 if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
2485                                         child_frame.obj = vt_sp;
2486                                         valuetype_this.data.p = vt_sp;
2487                                 } else {
2488                                         memset (&valuetype_this, 0, sizeof (stackval));
2489                                         child_frame.obj = &valuetype_this;
2490                                 }
2491                         } else {
2492                                 if (newobj_class != mono_defaults.string_class) {
2493                                         context->managed_code = 0;
2494                                         o = mono_object_new (context->domain, newobj_class);
2495                                         context->managed_code = 1;
2496                                         if (context->abort_thread) {
2497                                                 MonoThread *thread = mono_thread_current ();
2498                                                 context->abort_thread = 0;
2499                                                 thread->abort_exc = mono_get_exception_thread_abort ();        
2500                                                 frame->ex = thread->abort_exc;
2501                                                 goto handle_finally;
2502                                         }
2503                                         child_frame.obj = o;
2504                                 } else {
2505                                         child_frame.retval = &retval;
2506                                 }
2507                         }
2508
2509                         if (csig->param_count) {
2510                                 sp -= csig->param_count;
2511                                 child_frame.stack_args = sp;
2512                         } else {
2513                                 child_frame.stack_args = NULL;
2514                         }
2515
2516                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2517
2518                         child_frame.ip = NULL;
2519                         child_frame.ex = NULL;
2520
2521                         ves_exec_method_with_context (&child_frame, context);
2522
2523                         context->current_frame = frame;
2524
2525                         if (child_frame.ex) {
2526                                 /*
2527                                  * An exception occurred, need to run finally, fault and catch handlers..
2528                                  */
2529                                 frame->ex = child_frame.ex;
2530                                 goto handle_finally;
2531                         }
2532                         /*
2533                          * a constructor returns void, but we need to return the object we created
2534                          */
2535 array_constructed:
2536                         if (newobj_class->valuetype && !newobj_class->enumtype) {
2537                                 *sp = valuetype_this;
2538                         } else if (newobj_class == mono_defaults.string_class) {
2539                                 *sp = retval;
2540                         } else {
2541                                 sp->data.p = o;
2542                         }
2543                         ++sp;
2544                         MINT_IN_BREAK;
2545                 }
2546                 MINT_IN_CASE(MINT_CASTCLASS)
2547                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2548                         if ((o = sp [-1].data.p)) {
2549                                 if (c->marshalbyref) {
2550                                         if (!mono_object_isinst_mbyref (o, c))
2551                                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2552                                 } else {
2553                                         MonoVTable *vt = o->vtable;
2554                                         MonoClass *oklass = vt->klass;
2555                                         if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
2556                                                 if (c->interface_id > vt->max_interface_id ||
2557                                                     vt->interface_offsets [c->interface_id] == 0) {
2558                                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
2559                                                 }
2560                                         } else if (c->rank) {
2561                                                 if (!mono_object_isinst (o, c))
2562                                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
2563                                         } else if (!mono_class_has_parent (oklass, c)) {
2564                                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2565                                         }
2566                                 }
2567                         }
2568                         ip += 2;
2569                         MINT_IN_BREAK;
2570                 MINT_IN_CASE(MINT_ISINST)
2571                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2572                         if ((o = sp [-1].data.p)) {
2573                                 if (c->marshalbyref) {
2574                                         if (!mono_object_isinst_mbyref (o, c))
2575                                                 sp [-1].data.p = NULL;
2576                                 } else {
2577                                         MonoVTable *vt = o->vtable;
2578                                         MonoClass *oklass = vt->klass;
2579                                         if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
2580                                                 if (c->interface_id > vt->max_interface_id ||
2581                                                     vt->interface_offsets [c->interface_id] == 0) {
2582                                                         sp [-1].data.p = NULL;
2583                                                 }
2584                                         } else if (c->rank) {
2585                                                 if (!mono_object_isinst (o, c))
2586                                                         sp [-1].data.p = NULL;
2587                                         } else if (!mono_class_has_parent (oklass, c)) {
2588                                                 sp [-1].data.p = NULL;
2589                                         }
2590                                 }
2591                         }
2592                         ip += 2;
2593                         MINT_IN_BREAK;
2594                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
2595                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
2596                         ++ip;
2597                         MINT_IN_BREAK;
2598                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
2599                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
2600                         ++ip;
2601                         MINT_IN_BREAK;
2602                 MINT_IN_CASE(MINT_UNBOX)
2603                         c = rtm->data_items[*(guint16 *)(ip + 1)];
2604                         
2605                         o = sp [-1].data.p;
2606                         if (!o)
2607                                 THROW_EX (mono_get_exception_null_reference(), ip);
2608
2609                         if (!(mono_object_isinst (o, c) || 
2610                                   ((o->vtable->klass->rank == 0) && 
2611                                    (o->vtable->klass->element_class == c->element_class))))
2612                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2613
2614                         sp [-1].data.p = (char *)o + sizeof (MonoObject);
2615                         ip += 2;
2616                         MINT_IN_BREAK;
2617                 MINT_IN_CASE(MINT_THROW)
2618                         --sp;
2619                         frame->ex_handler = NULL;
2620                         if (!sp->data.p)
2621                                 sp->data.p = mono_get_exception_null_reference ();
2622                         THROW_EX ((MonoException *)sp->data.p, ip);
2623                         MINT_IN_BREAK;
2624                 MINT_IN_CASE(MINT_LDFLDA)
2625                         o = sp [-1].data.p;
2626                         if (!o)
2627                                 THROW_EX (mono_get_exception_null_reference (), ip);
2628                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
2629                         ip += 2;
2630                         MINT_IN_BREAK;
2631                 MINT_IN_CASE(MINT_CKNULL)
2632                         o = sp [-1].data.p;
2633                         if (!o)
2634                                 THROW_EX (mono_get_exception_null_reference (), ip);
2635                         ++ip;
2636                         MINT_IN_BREAK;
2637
2638 #define LDFLD(datamem, fieldtype) \
2639         o = sp [-1].data.p; \
2640         if (!o) \
2641                 THROW_EX (mono_get_exception_null_reference (), ip); \
2642         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
2643         ip += 2;
2644
2645                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
2646                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
2647                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
2648                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
2649                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
2650                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
2651                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
2652                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
2653                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
2654                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
2655
2656                 MINT_IN_CASE(MINT_LDFLD_VT)
2657                         o = sp [-1].data.p;
2658                         if (!o)
2659                                 THROW_EX (mono_get_exception_null_reference (), ip);
2660                         i32 = READ32(ip + 2);
2661                         sp [-1].data.p = vt_sp;
2662                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
2663                         vt_sp += (i32 + 7) & ~7;
2664                         ip += 4;
2665                         MINT_IN_BREAK;
2666
2667                 MINT_IN_CASE(MINT_LDRMFLD) {
2668                         MonoClassField *field;
2669                         char *addr;
2670
2671                         o = sp [-1].data.p;
2672                         if (!o)
2673                                 THROW_EX (mono_get_exception_null_reference (), ip);
2674                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2675                         ip += 2;
2676                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2677                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2678                                 addr = mono_load_remote_field (o, klass, field, NULL);
2679                         } else {
2680                                 addr = (char*)o + field->offset;
2681                         }                               
2682
2683                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
2684                         MINT_IN_BREAK;
2685                 }
2686
2687                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
2688                         MonoClassField *field;
2689                         char *addr;
2690
2691                         o = sp [-1].data.p;
2692                         if (!o)
2693                                 THROW_EX (mono_get_exception_null_reference (), ip);
2694                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2695                         i32 = READ32(ip + 2);
2696                         ip += 4;
2697                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2698                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2699                                 addr = mono_load_remote_field (o, klass, field, NULL);
2700                         } else {
2701                                 addr = (char*)o + field->offset;
2702                         }                               
2703
2704                         sp [-1].data.p = vt_sp;
2705                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
2706                         vt_sp += (i32 + 7) & ~7;
2707                         memcpy(sp [-1].data.p, addr, i32);
2708                         MINT_IN_BREAK;
2709                 }
2710
2711 #define STFLD(datamem, fieldtype) \
2712         o = sp [-2].data.p; \
2713         if (!o) \
2714                 THROW_EX (mono_get_exception_null_reference (), ip); \
2715         sp -= 2; \
2716         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
2717         ip += 2;
2718
2719                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
2720                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
2721                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
2722                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
2723                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
2724                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
2725                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
2726                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
2727                 MINT_IN_CASE(MINT_STFLD_O) STFLD(p, gpointer); MINT_IN_BREAK;
2728                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
2729
2730                 MINT_IN_CASE(MINT_STFLD_VT)
2731                         o = sp [-2].data.p;
2732                         if (!o)
2733                                 THROW_EX (mono_get_exception_null_reference (), ip);
2734                         i32 = READ32(ip + 2);
2735                         sp -= 2;
2736                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
2737                         vt_sp -= (i32 + 7) & ~7;
2738                         ip += 4;
2739                         MINT_IN_BREAK;
2740
2741                 MINT_IN_CASE(MINT_STRMFLD) {
2742                         MonoClassField *field;
2743
2744                         o = sp [-2].data.p;
2745                         if (!o)
2746                                 THROW_EX (mono_get_exception_null_reference (), ip);
2747                         
2748                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2749                         ip += 2;
2750
2751                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2752                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2753                                 mono_store_remote_field (o, klass, field, &sp [-1].data);
2754                         } else
2755                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
2756
2757                         sp -= 2;
2758                         MINT_IN_BREAK;
2759                 }
2760                 MINT_IN_CASE(MINT_STRMFLD_VT) {
2761                         MonoClassField *field;
2762
2763                         o = sp [-2].data.p;
2764                         if (!o)
2765                                 THROW_EX (mono_get_exception_null_reference (), ip);
2766                         field = rtm->data_items[* (guint16 *)(ip + 1)];
2767                         i32 = READ32(ip + 2);
2768                         ip += 4;
2769
2770                         if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
2771                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
2772                                 mono_store_remote_field (o, klass, field, &sp [-1].data);
2773                         } else
2774                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
2775
2776                         sp -= 2;
2777                         vt_sp -= (i32 + 7) & ~7;
2778                         MINT_IN_BREAK;
2779                 }
2780                 MINT_IN_CASE(MINT_LDSFLDA) {
2781                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2782                         MonoVTable *vt = mono_class_vtable (context->domain, field->parent);
2783                         gpointer addr;
2784
2785                         if (!vt->initialized) {
2786                                 frame->ip = ip;
2787                                 mono_runtime_class_init (vt);
2788                         }
2789                         ip += 2;
2790
2791                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2792                                 sp->data.p = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2793                         else
2794                                 sp->data.p = (char*)(vt->data) + field->offset;
2795                         ++sp;
2796                         MINT_IN_BREAK;
2797                 }
2798                 MINT_IN_CASE(MINT_LDSFLD) {
2799                         MonoVTable *vt;
2800                         MonoClassField *field;
2801                         gpointer addr;
2802
2803                         field = rtm->data_items[*(guint16 *)(ip + 1)];
2804                         vt = rtm->data_items [*(guint16 *)(ip + 2)];
2805                         if (!vt->initialized) {
2806                                 frame->ip = ip;
2807                                 mono_runtime_class_init (vt);
2808                         }
2809                         ip += 3;
2810                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2811                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2812                         else
2813                                 addr = (char*)(vt->data) + field->offset;
2814
2815                         stackval_from_data (field->type, sp, addr, FALSE);
2816                         ++sp;
2817                         MINT_IN_BREAK;
2818                 }
2819                 MINT_IN_CASE(MINT_LDSFLD_I4) {
2820                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2821                         MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
2822                         if (!vt->initialized) {
2823                                 frame->ip = ip;
2824                                 mono_runtime_class_init (vt);
2825                         }
2826                         ip += 3;
2827                         sp->data.i = * (gint32 *)((char*)(vt->data) + field->offset);
2828                         ++sp;
2829                         MINT_IN_BREAK;
2830                 }
2831                 MINT_IN_CASE(MINT_LDSFLD_O) {
2832                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
2833                         MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
2834                         if (!vt->initialized) {
2835                                 frame->ip = ip;
2836                                 mono_runtime_class_init (vt);
2837                         }
2838                         ip += 3;
2839                         sp->data.p = * (gpointer *)((char*)(vt->data) + field->offset);
2840                         ++sp;
2841                         MINT_IN_BREAK;
2842                 }
2843                 MINT_IN_CASE(MINT_LDSFLD_VT) {
2844                         MonoVTable *vt;
2845                         MonoClassField *field;
2846                         guint32 token;
2847                         gpointer addr;
2848                         int size;
2849
2850                         token = * (guint16 *)(ip + 1);
2851                         size = READ32(ip + 2);
2852                         field = rtm->data_items[token];
2853                         ip += 4;
2854                                                 
2855                         vt = mono_class_vtable (context->domain, field->parent);
2856                         if (!vt->initialized) {
2857                                 frame->ip = ip - 2;
2858                                 mono_runtime_class_init (vt);
2859                         }
2860                         
2861                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2862                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2863                         else
2864                                 addr = (char*)(vt->data) + field->offset;
2865
2866                         sp->data.p = vt_sp;
2867                         vt_sp += (size + 7) & ~7;
2868                         stackval_from_data (field->type, sp, addr, FALSE);
2869                         ++sp;
2870                         MINT_IN_BREAK;
2871                 }
2872                 MINT_IN_CASE(MINT_STSFLD) {
2873                         MonoVTable *vt;
2874                         MonoClassField *field;
2875                         guint32 token;
2876                         gpointer addr;
2877
2878                         token = * (guint16 *)(ip + 1);
2879                         field = rtm->data_items[token];
2880                         ip += 2;
2881                         --sp;
2882
2883                         vt = mono_class_vtable (context->domain, field->parent);
2884                         if (!vt->initialized) {
2885                                 frame->ip = ip - 2;
2886                                 mono_runtime_class_init (vt);
2887                         }
2888                         
2889                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2890                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2891                         else
2892                                 addr = (char*)(vt->data) + field->offset;
2893
2894                         stackval_to_data (field->type, sp, addr, FALSE);
2895                         MINT_IN_BREAK;
2896                 }
2897                 MINT_IN_CASE(MINT_STSFLD_VT) {
2898                         MonoVTable *vt;
2899                         MonoClassField *field;
2900                         guint32 token;
2901                         gpointer addr;
2902                         int size;
2903
2904                         token = * (guint16 *)(ip + 1);
2905                         size = READ32(ip + 2);
2906                         field = rtm->data_items[token];
2907                         ip += 4;
2908                                                 
2909                         vt = mono_class_vtable (context->domain, field->parent);
2910                         if (!vt->initialized) {
2911                                 frame->ip = ip - 2;
2912                                 mono_runtime_class_init (vt);
2913                         }
2914                         
2915                         if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
2916                                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
2917                         else
2918                                 addr = (char*)(vt->data) + field->offset;
2919                         --sp;
2920                         stackval_to_data (field->type, sp, addr, FALSE);
2921                         vt_sp -= (size + 7) & ~7;
2922                         MINT_IN_BREAK;
2923                 }
2924                 MINT_IN_CASE(MINT_STOBJ_VT) {
2925                         int size;
2926                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2927                         ip += 2;
2928                         size = mono_class_value_size (c, NULL);
2929                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
2930                         vt_sp -= (size + 7) & ~7;
2931                         sp -= 2;
2932                         MINT_IN_BREAK;
2933                 }
2934                 MINT_IN_CASE(MINT_STOBJ) {
2935                         int size;
2936                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2937                         ip += 2;
2938                         size = mono_class_value_size (c, NULL);
2939                         memcpy(sp [-2].data.p, &sp [-1].data, size);
2940                         sp -= 2;
2941                         MINT_IN_BREAK;
2942                 }
2943                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
2944                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
2945                                 THROW_EX (mono_get_exception_overflow (), ip);
2946                         sp [-1].data.i = (guint32)sp [-1].data.f;
2947                         ++ip;
2948                         MINT_IN_BREAK;
2949                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
2950                         if (sp [-1].data.i < 0)
2951                                 THROW_EX (mono_get_exception_overflow (), ip);
2952                         sp [-1].data.l = sp [-1].data.i;
2953                         ++ip;
2954                         MINT_IN_BREAK;
2955                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
2956                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
2957                         if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807LL)
2958                                 THROW_EX (mono_get_exception_overflow (), ip);
2959                         sp [-1].data.l = (guint64)sp [-1].data.f;
2960                         ++ip;
2961                         MINT_IN_BREAK;
2962                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
2963                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
2964                                 THROW_EX (mono_get_exception_overflow (), ip);
2965                         sp [-1].data.l = (gint64)sp [-1].data.f;
2966                         ++ip;
2967                         MINT_IN_BREAK;
2968                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
2969                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
2970                                 THROW_EX (mono_get_exception_overflow (), ip);
2971                         sp [-1].data.i = (mono_u)sp [-1].data.l;
2972                         ++ip;
2973                         MINT_IN_BREAK;
2974                 MINT_IN_CASE(MINT_BOX)
2975                         c = rtm->data_items [* (guint16 *)(ip + 1)];
2976
2977                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
2978                                 int size = mono_class_value_size (c, NULL);
2979                                 sp [-1].data.p = mono_value_box (context->domain, c, sp [-1].data.p);
2980                                 size = (size + 7) & ~7;
2981                                 vt_sp -= size;
2982                         }                               
2983                         else {
2984                                 stackval_to_data (&c->byval_arg, &sp [-1], (char*)&sp [-1], FALSE);
2985                                 sp [-1].data.p = mono_value_box (context->domain, c, &sp [-1]);
2986                         }
2987                         ip += 2;
2988                         MINT_IN_BREAK;
2989                 MINT_IN_CASE(MINT_NEWARR)
2990                         sp [-1].data.p = (MonoObject*) mono_array_new (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i);
2991                         ip += 2;
2992                         /*if (profiling_classes) {
2993                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
2994                                 count++;
2995                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
2996                         }*/
2997
2998                         MINT_IN_BREAK;
2999                 MINT_IN_CASE(MINT_LDLEN)
3000                         o = sp [-1].data.p;
3001                         if (!o)
3002                                 THROW_EX (mono_get_exception_null_reference (), ip);
3003                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3004                         ++ip;
3005                         MINT_IN_BREAK;
3006                 MINT_IN_CASE(MINT_GETCHR) {
3007                         MonoString *s;
3008                         s = sp [-2].data.p;
3009                         if (!s)
3010                                 THROW_EX (mono_get_exception_null_reference (), ip);
3011                         i32 = sp [-1].data.i;
3012                         if (i32 < 0 || i32 >= mono_string_length (s))
3013                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3014                         --sp;
3015                         sp [-1].data.i = mono_string_chars(s)[i32];
3016                         ++ip;
3017                         MINT_IN_BREAK;
3018                 }
3019                 MINT_IN_CASE(MINT_STRLEN)
3020                         ++ip;
3021                         sp [-1].data.i = mono_string_length ((MonoString*)sp [-1].data.p);
3022                         MINT_IN_BREAK;
3023                 MINT_IN_CASE(MINT_ARRAY_RANK)
3024                         o = sp [-1].data.p;
3025                         if (!o)
3026                                 THROW_EX (mono_get_exception_null_reference (), ip);
3027                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
3028                         ip++;
3029                         MINT_IN_BREAK;
3030                 MINT_IN_CASE(MINT_LDELEMA) {
3031                         guint32 esize;
3032                         mono_u aindex;
3033                         
3034                         /*token = READ32 (ip)*/;
3035                         ip += 2;
3036                         sp -= 2;
3037
3038                         o = sp [0].data.p;
3039
3040                         aindex = sp [1].data.i;
3041                         if (aindex >= mono_array_length ((MonoArray *) o))
3042                                 THROW_EX (mono_get_exception_index_out_of_range (), ip - 2);
3043
3044                         /* check the array element corresponds to token */
3045                         esize = mono_array_element_size (((MonoArray *) o)->obj.vtable->klass);
3046                         
3047                         sp->data.p = mono_array_addr_with_size ((MonoArray *) o, esize, aindex);
3048                         ++sp;
3049                         MINT_IN_BREAK;
3050                 }
3051                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
3052                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
3053                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
3054                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
3055                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
3056                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
3057                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
3058                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
3059                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
3060                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
3061                 MINT_IN_CASE(MINT_LDELEM_REF) {
3062                         MonoArray *o;
3063                         mono_u aindex;
3064
3065                         sp -= 2;
3066
3067                         o = sp [0].data.p;
3068                         if (!o)
3069                                 THROW_EX (mono_get_exception_null_reference (), ip);
3070
3071                         aindex = sp [1].data.i;
3072                         if (aindex >= mono_array_length (o))
3073                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3074
3075                         /*
3076                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3077                          */
3078                         switch (*ip) {
3079                         case MINT_LDELEM_I1:
3080                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
3081                                 break;
3082                         case MINT_LDELEM_U1:
3083                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
3084                                 break;
3085                         case MINT_LDELEM_I2:
3086                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
3087                                 break;
3088                         case MINT_LDELEM_U2:
3089                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
3090                                 break;
3091                         case MINT_LDELEM_I:
3092                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
3093                                 break;
3094                         case MINT_LDELEM_I4:
3095                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
3096                                 break;
3097                         case MINT_LDELEM_U4:
3098                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
3099                                 break;
3100                         case MINT_LDELEM_I8:
3101                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
3102                                 break;
3103                         case MINT_LDELEM_R4:
3104                                 sp [0].data.f = mono_array_get (o, float, aindex);
3105                                 break;
3106                         case MINT_LDELEM_R8:
3107                                 sp [0].data.f = mono_array_get (o, double, aindex);
3108                                 break;
3109                         case MINT_LDELEM_REF:
3110                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
3111                                 break;
3112                         default:
3113                                 ves_abort();
3114                         }
3115
3116                         ++ip;
3117                         ++sp;
3118                         MINT_IN_BREAK;
3119                 }
3120                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
3121                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
3122                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
3123                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
3124                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
3125                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
3126                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
3127                 MINT_IN_CASE(MINT_STELEM_REF) {
3128                         mono_u aindex;
3129
3130                         sp -= 3;
3131
3132                         o = sp [0].data.p;
3133                         if (!o)
3134                                 THROW_EX (mono_get_exception_null_reference (), ip);
3135
3136                         aindex = sp [1].data.i;
3137                         if (aindex >= mono_array_length ((MonoArray *)o))
3138                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3139
3140                         switch (*ip) {
3141                         case MINT_STELEM_I:
3142                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
3143                                 break;
3144                         case MINT_STELEM_I1:
3145                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
3146                                 break;
3147                         case MINT_STELEM_I2:
3148                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
3149                                 break;
3150                         case MINT_STELEM_I4:
3151                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
3152                                 break;
3153                         case MINT_STELEM_I8:
3154                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
3155                                 break;
3156                         case MINT_STELEM_R4:
3157                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
3158                                 break;
3159                         case MINT_STELEM_R8:
3160                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
3161                                 break;
3162                         case MINT_STELEM_REF:
3163                                 if (sp [2].data.p && !mono_object_isinst (sp [2].data.p, mono_object_class (o)->element_class))
3164                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
3165                                 mono_array_set ((MonoArray *)o, gpointer, aindex, sp [2].data.p);
3166                                 break;
3167                         default:
3168                                 ves_abort();
3169                         }
3170
3171                         ++ip;
3172                         MINT_IN_BREAK;
3173                 }
3174                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
3175                         if (sp [-1].data.i < 0)
3176                                 THROW_EX (mono_get_exception_overflow (), ip);
3177                         ++ip;
3178                         MINT_IN_BREAK;
3179                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
3180                         if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
3181                                 THROW_EX (mono_get_exception_overflow (), ip);
3182                         sp [-1].data.i = (gint32) sp [-1].data.l;
3183                         ++ip;
3184                         MINT_IN_BREAK;
3185                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
3186                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
3187                                 THROW_EX (mono_get_exception_overflow (), ip);
3188                         sp [-1].data.i = (gint32) sp [-1].data.f;
3189                         ++ip;
3190                         MINT_IN_BREAK;
3191                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
3192                         if (sp [-1].data.i < 0)
3193                                 THROW_EX (mono_get_exception_overflow (), ip);
3194                         ++ip;
3195                         MINT_IN_BREAK;
3196                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
3197                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
3198                                 THROW_EX (mono_get_exception_overflow (), ip);
3199                         sp [-1].data.i = (guint32) sp [-1].data.l;
3200                         ++ip;
3201                         MINT_IN_BREAK;
3202                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
3203                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3204                                 THROW_EX (mono_get_exception_overflow (), ip);
3205                         sp [-1].data.i = (guint32) sp [-1].data.f;
3206                         ++ip;
3207                         MINT_IN_BREAK;
3208                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
3209                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
3210                                 THROW_EX (mono_get_exception_overflow (), ip);
3211                         ++ip;
3212                         MINT_IN_BREAK;
3213                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
3214                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
3215                                 THROW_EX (mono_get_exception_overflow (), ip);
3216                         sp [-1].data.i = (gint16) sp [-1].data.l;
3217                         ++ip;
3218                         MINT_IN_BREAK;
3219                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
3220                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
3221                                 THROW_EX (mono_get_exception_overflow (), ip);
3222                         sp [-1].data.i = (gint16) sp [-1].data.f;
3223                         ++ip;
3224                         MINT_IN_BREAK;
3225                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
3226                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
3227                                 THROW_EX (mono_get_exception_overflow (), ip);
3228                         ++ip;
3229                         MINT_IN_BREAK;
3230                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
3231                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
3232                                 THROW_EX (mono_get_exception_overflow (), ip);
3233                         sp [-1].data.i = (guint16) sp [-1].data.l;
3234                         ++ip;
3235                         MINT_IN_BREAK;
3236                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
3237                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
3238                                 THROW_EX (mono_get_exception_overflow (), ip);
3239                         sp [-1].data.i = (guint16) sp [-1].data.f;
3240                         ++ip;
3241                         MINT_IN_BREAK;
3242                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
3243                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
3244                                 THROW_EX (mono_get_exception_overflow (), ip);
3245                         ++ip;
3246                         MINT_IN_BREAK;
3247                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
3248                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
3249                                 THROW_EX (mono_get_exception_overflow (), ip);
3250                         sp [-1].data.i = (gint8) sp [-1].data.l;
3251                         ++ip;
3252                         MINT_IN_BREAK;
3253                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
3254                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
3255                                 THROW_EX (mono_get_exception_overflow (), ip);
3256                         sp [-1].data.i = (gint8) sp [-1].data.f;
3257                         ++ip;
3258                         MINT_IN_BREAK;
3259                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
3260                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
3261                                 THROW_EX (mono_get_exception_overflow (), ip);
3262                         ++ip;
3263                         MINT_IN_BREAK;
3264                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
3265                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
3266                                 THROW_EX (mono_get_exception_overflow (), ip);
3267                         sp [-1].data.i = (guint8) sp [-1].data.l;
3268                         ++ip;
3269                         MINT_IN_BREAK;
3270                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
3271                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
3272                                 THROW_EX (mono_get_exception_overflow (), ip);
3273                         sp [-1].data.i = (guint8) sp [-1].data.f;
3274                         ++ip;
3275                         MINT_IN_BREAK;
3276 #if 0
3277                 MINT_IN_CASE(MINT_LDELEM) 
3278                 MINT_IN_CASE(MINT_STELEM) 
3279                 MINT_IN_CASE(MINT_UNBOX_ANY) 
3280
3281                 MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
3282 #endif
3283                 MINT_IN_CASE(MINT_CKFINITE)
3284                         if (!finite(sp [-1].data.f))
3285                                 THROW_EX (mono_get_exception_arithmetic (), ip);
3286                         ++ip;
3287                         MINT_IN_BREAK;
3288 #if 0
3289                 MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
3290 #endif
3291                 MINT_IN_CASE(MINT_LDTOKEN)
3292                         sp->data.p = vt_sp;
3293                         vt_sp += 8;
3294                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
3295                         ip += 2;
3296                         ++sp;
3297                         MINT_IN_BREAK;
3298                 MINT_IN_CASE(MINT_ADD_OVF_I4)
3299                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3300                                 THROW_EX (mono_get_exception_overflow (), ip);
3301                         BINOP(i, +);
3302                         MINT_IN_BREAK;
3303                 MINT_IN_CASE(MINT_ADD_OVF_I8)
3304                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3305                                 THROW_EX (mono_get_exception_overflow (), ip);
3306                         BINOP(l, +);
3307                         MINT_IN_BREAK;
3308                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
3309                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3310                                 THROW_EX (mono_get_exception_overflow (), ip);
3311                         BINOP_CAST(i, +, guint32);
3312                         MINT_IN_BREAK;
3313                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
3314                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3315                                 THROW_EX (mono_get_exception_overflow (), ip);
3316                         BINOP_CAST(l, +, guint64);
3317                         MINT_IN_BREAK;
3318                 MINT_IN_CASE(MINT_MUL_OVF_I4)
3319                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3320                                 THROW_EX (mono_get_exception_overflow (), ip);
3321                         BINOP(i, *);
3322                         MINT_IN_BREAK;
3323                 MINT_IN_CASE(MINT_MUL_OVF_I8)
3324                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3325                                 THROW_EX (mono_get_exception_overflow (), ip);
3326                         BINOP(l, *);
3327                         MINT_IN_BREAK;
3328                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
3329                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3330                                 THROW_EX (mono_get_exception_overflow (), ip);
3331                         BINOP_CAST(i, *, guint32);
3332                         MINT_IN_BREAK;
3333                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
3334                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3335                                 THROW_EX (mono_get_exception_overflow (), ip);
3336                         BINOP_CAST(l, *, guint64);
3337                         MINT_IN_BREAK;
3338                 MINT_IN_CASE(MINT_SUB_OVF_I4)
3339                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3340                                 THROW_EX (mono_get_exception_overflow (), ip);
3341                         BINOP(i, -);
3342                         MINT_IN_BREAK;
3343                 MINT_IN_CASE(MINT_SUB_OVF_I8)
3344                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3345                                 THROW_EX (mono_get_exception_overflow (), ip);
3346                         BINOP(l, -);
3347                         MINT_IN_BREAK;
3348                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
3349                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3350                                 THROW_EX (mono_get_exception_overflow (), ip);
3351                         BINOP_CAST(i, -, guint32);
3352                         MINT_IN_BREAK;
3353                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
3354                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3355                                 THROW_EX (mono_get_exception_overflow (), ip);
3356                         BINOP_CAST(l, -, guint64);
3357                         MINT_IN_BREAK;
3358                 MINT_IN_CASE(MINT_ENDFINALLY)
3359                         if (finally_ips) {
3360                                 ip = finally_ips->data;
3361                                 finally_ips = g_slist_remove (finally_ips, ip);
3362                                 goto main_loop;
3363                         }
3364                         if (frame->ex)
3365                                 goto handle_fault;
3366                         ves_abort();
3367                         MINT_IN_BREAK;
3368                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
3369                 MINT_IN_CASE(MINT_LEAVE_S)
3370                         while (sp > frame->stack) {
3371                                 --sp;
3372                         }
3373                         frame->ip = ip;
3374                         if (*ip == MINT_LEAVE_S) {
3375                                 ip += (short) *(ip + 1);
3376                         } else {
3377                                 ip += (gint32) READ32 (ip + 1);
3378                         }
3379                         endfinally_ip = ip;
3380                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
3381                                 frame->ex_handler = NULL;
3382                                 frame->ex = NULL;
3383                         }
3384                         goto handle_finally;
3385                         MINT_IN_BREAK;
3386                 MINT_IN_CASE(MINT_MONO_CONV1)
3387                         ip += 2;
3388                         switch (ip [-1]) {
3389                         case MONO_MARSHAL_CONV_STR_LPWSTR:
3390                                 sp [-1].data.p = mono_string_to_utf16 (sp [-1].data.p);
3391                                 MINT_IN_BREAK;
3392                         case MONO_MARSHAL_CONV_LPSTR_STR:
3393                                 sp [-1].data.p = mono_string_new_wrapper (sp [-1].data.p);
3394                                 MINT_IN_BREAK;
3395                         case MONO_MARSHAL_CONV_STR_LPTSTR:
3396                         case MONO_MARSHAL_CONV_STR_LPSTR:
3397                                 sp [-1].data.p = mono_string_to_utf8 (sp [-1].data.p);
3398                                 MINT_IN_BREAK;
3399                         case MONO_MARSHAL_CONV_STR_BSTR:
3400                                 sp [-1].data.p = mono_string_to_bstr (sp [-1].data.p);
3401                                 MINT_IN_BREAK;
3402                         case MONO_MARSHAL_CONV_STR_TBSTR:
3403                         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3404                                 sp [-1].data.p = mono_string_to_ansibstr (sp [-1].data.p);
3405                                 MINT_IN_BREAK;
3406                         case MONO_MARSHAL_CONV_SB_LPSTR:
3407                         case MONO_MARSHAL_CONV_SB_LPTSTR:
3408                                 sp [-1].data.p = mono_string_builder_to_utf8 (sp [-1].data.p);
3409                                 MINT_IN_BREAK;
3410                         case MONO_MARSHAL_CONV_SB_LPWSTR:
3411                                 sp [-1].data.p = mono_string_builder_to_utf16 (sp [-1].data.p);
3412                                 MINT_IN_BREAK;
3413                         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
3414                                 sp [-1].data.p = mono_array_to_savearray (sp [-1].data.p);
3415                                 MINT_IN_BREAK;
3416                         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
3417                                 sp [-1].data.p = mono_array_to_lparray (sp [-1].data.p);
3418                                 MINT_IN_BREAK;
3419                         case MONO_MARSHAL_CONV_DEL_FTN:
3420                                 sp [-1].data.p = mono_delegate_to_ftnptr (sp [-1].data.p);
3421                                 MINT_IN_BREAK;
3422                         case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
3423                                 sp [-1].data.p = mono_marshal_string_array (sp [-1].data.p);
3424                                 MINT_IN_BREAK;
3425                         case MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY:
3426                                 sp [-1].data.p = mono_marshal_string_array_to_unicode (sp [-1].data.p);
3427                                 break;
3428                         case MONO_MARSHAL_CONV_LPWSTR_STR:
3429                                 sp [-1].data.p = mono_string_from_utf16 (sp [-1].data.p);
3430                                 MINT_IN_BREAK;
3431                         default:
3432                                 fprintf(stderr, "MINT_MONO_CONV1 %d", ip[-1]);
3433                                 g_assert_not_reached ();
3434                         }
3435                         MINT_IN_BREAK;
3436                 MINT_IN_CASE(MINT_MONO_CONV2)
3437                         sp -= 2;
3438                         ip += 2;
3439                         switch (ip [-1]) {
3440                         case MONO_MARSHAL_CONV_LPSTR_SB:
3441                         case MONO_MARSHAL_CONV_LPTSTR_SB:
3442                                 mono_string_utf8_to_builder (sp [0].data.p, sp [1].data.p);
3443                                 MINT_IN_BREAK;
3444                         case MONO_MARSHAL_CONV_LPWSTR_SB:
3445                                 mono_string_utf16_to_builder (sp [0].data.p, sp [1].data.p);
3446                                 MINT_IN_BREAK;
3447                         case MONO_MARSHAL_FREE_ARRAY:
3448                                 mono_marshal_free_array (sp [0].data.p, sp [1].data.i);
3449                                 MINT_IN_BREAK;
3450                         default:
3451                                 g_assert_not_reached ();
3452                         }                                
3453                         MINT_IN_BREAK;
3454                 MINT_IN_CASE(MINT_MONO_CONV3)
3455                         sp -= 3;
3456                         ip += 2;
3457                         switch (ip [-1]) {
3458                         case MONO_MARSHAL_CONV_STR_BYVALSTR:
3459                                 mono_string_to_byvalstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
3460                                 MINT_IN_BREAK;
3461                         case MONO_MARSHAL_CONV_STR_BYVALWSTR:
3462                                 mono_string_to_byvalwstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
3463                                 MINT_IN_BREAK;
3464                         default:
3465                                 g_assert_not_reached ();
3466                         }
3467                         MINT_IN_BREAK;
3468                 MINT_IN_CASE(MINT_MONO_LDPTR)
3469                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
3470                         ip += 2;
3471                         ++sp;
3472                         MINT_IN_BREAK;
3473                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
3474                         sp->data.p = mono_object_new (context->domain, rtm->data_items [*(guint16 *)(ip + 1)]);
3475                         ip += 2;
3476                         sp++;
3477                         MINT_IN_BREAK;
3478                 MINT_IN_CASE(MINT_MONO_FREE)
3479                         ++ip;
3480                         --sp;
3481                         g_free (sp->data.p);
3482                         MINT_IN_BREAK;
3483                 MINT_IN_CASE(MINT_MONO_RETOBJ)
3484                         ++ip;
3485                         sp--;
3486                         stackval_from_data (frame->runtime_method->method->signature->ret, frame->retval, sp->data.p, frame->runtime_method->method->signature->pinvoke);
3487                         if (sp > frame->stack)
3488                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
3489                         goto exit_frame;
3490
3491 #define RELOP(datamem, op) \
3492         --sp; \
3493         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
3494         ++ip;
3495                 MINT_IN_CASE(MINT_CEQ_I4)
3496                         RELOP(i, ==);
3497                         MINT_IN_BREAK;
3498                 MINT_IN_CASE(MINT_CEQ0_I4)
3499                         sp [-1].data.i = (sp [-1].data.i == 0);
3500                         ++ip;
3501                         MINT_IN_BREAK;
3502                 MINT_IN_CASE(MINT_CEQ_I8)
3503                         RELOP(l, ==);
3504                         MINT_IN_BREAK;
3505                 MINT_IN_CASE(MINT_CEQ_R8)
3506                         --sp; 
3507                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3508                                 sp [-1].data.i = 0;
3509                         else
3510                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
3511                         ++ip;
3512                         MINT_IN_BREAK;
3513                 MINT_IN_CASE(MINT_CGT_I4)
3514                         RELOP(i, >);
3515                         MINT_IN_BREAK;
3516                 MINT_IN_CASE(MINT_CGT_I8)
3517                         RELOP(l, >);
3518                         MINT_IN_BREAK;
3519                 MINT_IN_CASE(MINT_CGT_R8)
3520                         --sp; 
3521                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3522                                 sp [-1].data.i = 0;
3523                         else
3524                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3525                         ++ip;
3526                         MINT_IN_BREAK;
3527
3528 #define RELOP_CAST(datamem, op, type) \
3529         --sp; \
3530         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3531         ++ip;
3532
3533                 MINT_IN_CASE(MINT_CGT_UN_I4)
3534                         RELOP_CAST(i, >, guint32);
3535                         MINT_IN_BREAK;
3536                 MINT_IN_CASE(MINT_CGT_UN_I8)
3537                         RELOP_CAST(l, >, guint64);
3538                         MINT_IN_BREAK;
3539                 MINT_IN_CASE(MINT_CGT_UN_R8)
3540                         --sp; 
3541                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3542                                 sp [-1].data.i = 1;
3543                         else
3544                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3545                         ++ip;
3546                         MINT_IN_BREAK;
3547                 MINT_IN_CASE(MINT_CLT_I4)
3548                         RELOP(i, <);
3549                         MINT_IN_BREAK;
3550                 MINT_IN_CASE(MINT_CLT_I8)
3551                         RELOP(l, <);
3552                         MINT_IN_BREAK;
3553                 MINT_IN_CASE(MINT_CLT_R8)
3554                         --sp; 
3555                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3556                                 sp [-1].data.i = 0;
3557                         else
3558                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3559                         ++ip;
3560                         MINT_IN_BREAK;
3561                 MINT_IN_CASE(MINT_CLT_UN_I4)
3562                         RELOP_CAST(i, <, guint32);
3563                         MINT_IN_BREAK;
3564                 MINT_IN_CASE(MINT_CLT_UN_I8)
3565                         RELOP_CAST(l, <, guint64);
3566                         MINT_IN_BREAK;
3567                 MINT_IN_CASE(MINT_CLT_UN_R8)
3568                         --sp; 
3569                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3570                                 sp [-1].data.i = 1;
3571                         else
3572                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3573                         ++ip;
3574                         MINT_IN_BREAK;
3575                 MINT_IN_CASE(MINT_LDFTN) {
3576                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3577                         ++sp;
3578                         ip += 2;
3579                         MINT_IN_BREAK;
3580                 }
3581                 MINT_IN_CASE(MINT_LDVIRTFTN) {
3582                         RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
3583                         ip += 2;
3584                         --sp;
3585                         if (!sp->data.p)
3586                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
3587                                 
3588                         sp->data.p = get_virtual_method (m, sp->data.p);
3589                         ++sp;
3590                         MINT_IN_BREAK;
3591                 }
3592
3593                 MINT_IN_CASE(MINT_LDTHIS)
3594                         sp->data.p = frame->obj;
3595                         ++ip;
3596                         ++sp; 
3597                         MINT_IN_BREAK;
3598                 MINT_IN_CASE(MINT_STTHIS)
3599                         --sp; 
3600                         frame->obj = sp->data.p;
3601                         ++ip;
3602                         MINT_IN_BREAK;
3603                 MINT_IN_CASE(MINT_LDTHISA)
3604                         sp->data.p = &frame->obj;
3605                         ++ip;
3606                         ++sp; 
3607                         MINT_IN_BREAK;
3608
3609 #define LDARG(datamem, argtype) \
3610         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
3611         ip += 2; \
3612         ++sp; 
3613         
3614                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
3615                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
3616                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
3617                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
3618                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
3619                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
3620                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
3621                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
3622                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
3623                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
3624
3625                 MINT_IN_CASE(MINT_LDARG_VT)
3626                         sp->data.p = vt_sp;
3627                         i32 = READ32(ip + 2);
3628                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
3629                         vt_sp += (i32 + 7) & ~7;
3630                         ip += 4;
3631                         ++sp;
3632                         MINT_IN_BREAK;
3633
3634 #define STARG(datamem, argtype) \
3635         --sp; \
3636         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3637         ip += 2; \
3638         
3639                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
3640                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
3641                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
3642                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
3643                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
3644                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
3645                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
3646                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
3647                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
3648                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
3649
3650                 MINT_IN_CASE(MINT_STARG_VT) 
3651                         i32 = READ32(ip + 2);
3652                         --sp;
3653                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
3654                         vt_sp -= (i32 + 7) & ~7;
3655                         ip += 4;
3656                         MINT_IN_BREAK;
3657
3658 #define STINARG(datamem, argtype) \
3659         do { \
3660                 int n = * (guint16 *)(ip + 1); \
3661                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
3662                 ip += 2; \
3663         } while (0)
3664         
3665                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
3666                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
3667                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
3668                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
3669                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
3670                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
3671                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
3672                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
3673                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
3674                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
3675
3676                 MINT_IN_CASE(MINT_STINARG_VT) {
3677                         int n = * (guint16 *)(ip + 1);
3678                         i32 = READ32(ip + 2);
3679                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
3680                         ip += 4;
3681                         MINT_IN_BREAK;
3682                 }
3683
3684                 MINT_IN_CASE(MINT_LDARGA)
3685                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
3686                         ip += 2;
3687                         ++sp;
3688                         MINT_IN_BREAK;
3689
3690 #define LDLOC(datamem, argtype) \
3691         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
3692         ip += 2; \
3693         ++sp; 
3694         
3695                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
3696                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
3697                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
3698                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
3699                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
3700                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
3701                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
3702                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
3703                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
3704                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
3705
3706                 MINT_IN_CASE(MINT_LDLOC_VT)
3707                         sp->data.p = vt_sp;
3708                         i32 = READ32(ip + 2);
3709                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
3710                         vt_sp += (i32 + 7) & ~7;
3711                         ip += 4;
3712                         ++sp;
3713                         MINT_IN_BREAK;
3714
3715                 MINT_IN_CASE(MINT_LDLOCA_S)
3716                         sp->data.p = locals + * (guint16 *)(ip + 1);
3717                         ip += 2;
3718                         ++sp;
3719                         MINT_IN_BREAK;
3720
3721 #define STLOC(datamem, argtype) \
3722         --sp; \
3723         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3724         ip += 2;
3725         
3726                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
3727                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
3728                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
3729                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
3730                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
3731                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
3732                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
3733                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
3734                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
3735                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
3736
3737 #define STLOC_NP(datamem, argtype) \
3738         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
3739         ip += 2;
3740
3741                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
3742                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
3743
3744                 MINT_IN_CASE(MINT_STLOC_VT)
3745                         i32 = READ32(ip + 2);
3746                         --sp;
3747                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
3748                         vt_sp -= (i32 + 7) & ~7;
3749                         ip += 4;
3750                         MINT_IN_BREAK;
3751
3752                 MINT_IN_CASE(MINT_LOCALLOC)
3753                         if (sp != frame->stack + 1) /*FIX?*/
3754                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
3755                         sp [-1].data.p = alloca (sp [-1].data.i);
3756                         ++ip;
3757                         MINT_IN_BREAK;
3758 #if 0
3759                 MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
3760 #endif
3761                 MINT_IN_CASE(MINT_INITOBJ)
3762                         --sp;
3763                         memset (sp->data.vt, 0, READ32(ip + 1));
3764                         ip += 3;
3765                         MINT_IN_BREAK;
3766                 MINT_IN_CASE(MINT_CPBLK)
3767                         sp -= 3;
3768                         if (!sp [0].data.p || !sp [1].data.p)
3769                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
3770                         ++ip;
3771                         /* FIXME: value and size may be int64... */
3772                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
3773                         MINT_IN_BREAK;
3774 #if 0
3775                 MINT_IN_CASE(MINT_CONSTRAINED_) {
3776                         guint32 token;
3777                         /* FIXME: implement */
3778                         ++ip;
3779                         token = READ32 (ip);
3780                         ip += 2;
3781                         MINT_IN_BREAK;
3782                 }
3783 #endif
3784                 MINT_IN_CASE(MINT_INITBLK)
3785                         sp -= 3;
3786                         if (!sp [0].data.p)
3787                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
3788                         ++ip;
3789                         /* FIXME: value and size may be int64... */
3790                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
3791                         MINT_IN_BREAK;
3792 #if 0
3793                 MINT_IN_CASE(MINT_NO_)
3794                         /* FIXME: implement */
3795                         ip += 2;
3796                         MINT_IN_BREAK;
3797 #endif
3798                 MINT_IN_CASE(MINT_RETHROW)
3799                         /* 
3800                          * need to clarify what this should actually do:
3801                          * start the search from the last found handler in
3802                          * this method or continue in the caller or what.
3803                          * Also, do we need to run finally/fault handlers after a retrow?
3804                          * Well, this implementation will follow the usual search
3805                          * for an handler, considering the current ip as throw spot.
3806                          * We need to NULL frame->ex_handler for the later code to
3807                          * actually run the new found handler.
3808                          */
3809                         frame->ex_handler = NULL;
3810                         THROW_EX (frame->ex, ip - 1);
3811                         MINT_IN_BREAK;
3812                 MINT_IN_DEFAULT
3813                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
3814                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
3815                 }
3816         }
3817
3818         g_assert_not_reached ();
3819         /*
3820          * Exception handling code.
3821          * The exception object is stored in frame->ex.
3822          */
3823
3824         handle_exception:
3825         {
3826                 int i;
3827                 guint32 ip_offset;
3828                 MonoInvocation *inv;
3829                 MonoExceptionClause *clause;
3830                 /*char *message;*/
3831                 MonoObject *ex_obj;
3832
3833 #if DEBUG_INTERP
3834                 if (tracing)
3835                         g_print ("* Handling exception '%s' at IL_%04x\n", 
3836                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
3837                                 rtm == NULL ? 0 : frame->ip - rtm->code);
3838 #endif
3839                 if (die_on_exception)
3840                         goto die_on_ex;
3841
3842                 for (inv = frame; inv; inv = inv->parent) {
3843                         MonoMethod *method;
3844                         if (inv->runtime_method == NULL)
3845                                 continue;
3846                         method = inv->runtime_method->method;
3847                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
3848                                 continue;
3849                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
3850                                 continue;
3851                         if (inv->ip == NULL)
3852                                 continue;
3853                         ip_offset = inv->ip - inv->runtime_method->code;
3854                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
3855                         for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
3856                                 clause = &inv->runtime_method->clauses [i];
3857                                 if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3858                                         if (!clause->flags) {
3859                                                 if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (method->klass->image, clause->token_or_filter))) {
3860                                                         /* 
3861                                                          * OK, we found an handler, now we need to execute the finally
3862                                                          * and fault blocks before branching to the handler code.
3863                                                          */
3864                                                         inv->ex_handler = clause;
3865 #if DEBUG_INTERP
3866                                                         if (tracing)
3867                                                                 g_print ("* Found handler at '%s'\n", method->name);
3868 #endif
3869                                                         goto handle_finally;
3870                                                 }
3871                                         } else {
3872                                                 /* FIXME: handle filter clauses */
3873                                                 g_assert (0);
3874                                         }
3875                                 }
3876                         }
3877                 }
3878                 /*
3879                  * If we get here, no handler was found: print a stack trace.
3880                  */
3881                 for (inv = frame; inv; inv = inv->parent) {
3882                         if (inv->invoke_trap)
3883                                 goto handle_finally;
3884                 }
3885 die_on_ex:
3886                 ex_obj = (MonoObject*)frame->ex;
3887                 mono_unhandled_exception (ex_obj);
3888                 exit (1);
3889         }
3890         handle_finally:
3891         {
3892                 int i;
3893                 guint32 ip_offset;
3894                 MonoExceptionClause *clause;
3895                 GSList *old_list = finally_ips;
3896                 MonoMethod *method = frame->runtime_method->method;
3897                 MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
3898                 
3899 #if DEBUG_INTERP
3900                 if (tracing)
3901                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
3902 #endif
3903                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
3904                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
3905                         goto exit_frame;
3906                 }
3907                 ip_offset = frame->ip - rtm->code;
3908
3909                 if (endfinally_ip != NULL)
3910                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
3911                 for (i = 0; i < header->num_clauses; ++i)
3912                         if (frame->ex_handler == &rtm->clauses [i])
3913                                 break;
3914                 while (i > 0) {
3915                         --i;
3916                         clause = &rtm->clauses [i];
3917                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
3918                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
3919                                         ip = rtm->code + clause->handler_offset;
3920                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
3921 #if DEBUG_INTERP
3922                                         if (tracing)
3923                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
3924 #endif
3925                                 }
3926                         }
3927                 }
3928
3929                 endfinally_ip = NULL;
3930
3931                 if (old_list != finally_ips && finally_ips) {
3932                         ip = finally_ips->data;
3933                         finally_ips = g_slist_remove (finally_ips, ip);
3934                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
3935                         goto main_loop;
3936                 }
3937
3938                 /*
3939                  * If an exception is set, we need to execute the fault handler, too,
3940                  * otherwise, we continue normally.
3941                  */
3942                 if (frame->ex)
3943                         goto handle_fault;
3944                 ves_abort();
3945         }
3946         handle_fault:
3947         {
3948                 int i;
3949                 guint32 ip_offset;
3950                 MonoExceptionClause *clause;
3951                 MonoMethodHeader *header = ((MonoMethodNormal *)frame->runtime_method->method)->header;
3952                 
3953 #if DEBUG_INTERP
3954                 if (tracing)
3955                         g_print ("* Handle fault\n");
3956 #endif
3957                 ip_offset = frame->ip - rtm->code;
3958                 for (i = 0; i < header->num_clauses; ++i) {
3959                         clause = &rtm->clauses [i];
3960                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3961                                 ip = rtm->code + clause->handler_offset;
3962 #if DEBUG_INTERP
3963                                 if (tracing)
3964                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
3965 #endif
3966                                 goto main_loop;
3967                         }
3968                 }
3969                 /*
3970                  * If the handler for the exception was found in this method, we jump
3971                  * to it right away, otherwise we return and let the caller run
3972                  * the finally, fault and catch blocks.
3973                  * This same code should be present in the endfault opcode, but it
3974                  * is corrently not assigned in the ECMA specs: LAMESPEC.
3975                  */
3976                 if (frame->ex_handler) {
3977 #if DEBUG_INTERP
3978                         if (tracing)
3979                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
3980 #endif
3981                         ip = rtm->code + frame->ex_handler->handler_offset;
3982                         sp = frame->stack;
3983                         vt_sp = (char *)sp + rtm->stack_size;
3984                         sp->data.p = frame->ex;
3985                         ++sp;
3986                         goto main_loop;
3987                 }
3988                 goto exit_frame;
3989         }
3990 exit_frame:
3991         DEBUG_LEAVE ();
3992 }
3993
3994 void
3995 ves_exec_method (MonoInvocation *frame)
3996 {
3997         ThreadContext *context = TlsGetValue (thread_context_id);
3998         ThreadContext context_struct;
3999         jmp_buf env;
4000
4001         frame->ex = NULL;
4002
4003         if (setjmp(env)) {
4004                 mono_unhandled_exception ((MonoObject*)frame->ex);
4005                 return;
4006         }
4007         if (context == NULL) {
4008                 context = &context_struct;
4009                 context_struct.domain = mono_domain_get ();
4010                 context_struct.base_frame = frame;
4011                 context_struct.current_frame = NULL;
4012                 context_struct.env_frame = frame;
4013                 context_struct.current_env = &env;
4014                 context_struct.search_for_handler = 0;
4015                 context_struct.managed_code = 0;
4016                 context_struct.abort_thread = 0;
4017                 TlsSetValue (thread_context_id, context);
4018         }
4019         frame->ip = NULL;
4020         frame->parent = context->current_frame;
4021         frame->runtime_method = mono_interp_get_runtime_method (frame->method);
4022         context->managed_code = 1;
4023         ves_exec_method_with_context(frame, context);
4024         context->managed_code = 0;
4025         if (frame->ex) {
4026                 if (context != &context_struct && context->current_env) {
4027                         context->env_frame->ex = frame->ex;
4028                         longjmp (*context->current_env, 1);
4029                 }
4030                 else
4031                         mono_unhandled_exception ((MonoObject*)frame->ex);
4032         }
4033         if (context->base_frame == frame)
4034                 TlsSetValue (thread_context_id, NULL);
4035         else
4036                 context->current_frame = frame->parent;
4037 }
4038
4039 static int 
4040 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4041 {
4042         MonoImage *image = assembly->image;
4043         MonoCLIImageInfo *iinfo;
4044         MonoMethod *method;
4045         MonoObject *exc = NULL;
4046         int rval;
4047
4048         iinfo = image->image_info;
4049         method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
4050         if (!method)
4051                 g_error ("No entry point method found in %s", image->name);
4052
4053         rval = mono_runtime_run_main (method, argc, argv, &exc);
4054         if (exc != NULL)
4055                 mono_unhandled_exception (exc);
4056
4057         return rval;
4058 }
4059
4060 static void
4061 usage (void)
4062 {
4063         fprintf (stderr,
4064                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4065                  "Usage is: mint [options] executable args...\n\n", VERSION);
4066         fprintf (stderr,
4067                  "Runtime Debugging:\n"
4068 #ifdef DEBUG_INTERP
4069                  "   --debug\n"
4070 #endif
4071                  "   --dieonex\n"
4072                  "   --noptr\t\t\tdon't print pointer addresses in trace output\n"
4073                  "   --opcode-count\n"
4074                  "   --print-vtable\n"
4075                  "   --traceclassinit\n"
4076                  "\n"
4077                  "Development:\n"
4078                  "   --debug method_name\n"
4079                  "   --profile\n"
4080                  "   --trace\n"
4081                  "   --traceops\n"
4082                  "\n"
4083                  "Runtime:\n"
4084                  "   --config filename  load the specified config file instead of the default\n"
4085                  "   --workers n        maximum number of worker threads\n"
4086                 );
4087         exit (1);
4088 }
4089
4090 #ifdef RUN_TEST
4091 static void
4092 test_load_class (MonoImage* image)
4093 {
4094         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
4095         MonoClass *klass;
4096         int i;
4097
4098         for (i = 1; i <= t->rows; ++i) {
4099                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
4100                 mono_class_init (klass);
4101         }
4102 }
4103 #endif
4104
4105 static void
4106 add_signal_handler (int signo, void (*handler)(int))
4107 {
4108 #ifdef PLATFORM_WIN32
4109         signal (signo, handler);
4110 #else
4111         struct sigaction sa;
4112
4113         sa.sa_handler = handler;
4114         sigemptyset (&sa.sa_mask);
4115         sa.sa_flags = 0;
4116
4117         g_assert (sigaction (signo, &sa, NULL) != -1);
4118 #endif
4119 }
4120
4121 static void
4122 segv_handler (int signum)
4123 {
4124         ThreadContext *context = TlsGetValue (thread_context_id);
4125         MonoException *segv_exception;
4126
4127         if (context == NULL)
4128                 return;
4129         segv_exception = mono_get_exception_null_reference ();
4130         segv_exception->message = mono_string_new (mono_domain_get (), "Null Reference (SIGSEGV)");
4131         mono_raise_exception (segv_exception);
4132 }
4133
4134
4135 static void
4136 quit_handler (int signum)
4137 {
4138         ThreadContext *context = TlsGetValue (thread_context_id);
4139         MonoException *quit_exception;
4140
4141         if (context == NULL)
4142                 return;
4143         quit_exception = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
4144         mono_raise_exception (quit_exception);
4145 }
4146
4147 static void
4148 abrt_handler (int signum)
4149 {
4150         ThreadContext *context = TlsGetValue (thread_context_id);
4151         MonoException *abrt_exception;
4152
4153         if (context == NULL)
4154                 return;
4155         abrt_exception = mono_get_exception_execution_engine ("Abort (SIGABRT).");
4156         mono_raise_exception (abrt_exception);
4157 }
4158
4159 static void
4160 thread_abort_handler (int signum)
4161 {
4162         ThreadContext *context = TlsGetValue (thread_context_id);
4163         MonoThread *thread;
4164
4165         if (context == NULL)
4166                 return;
4167
4168         if (context->managed_code) {
4169                 thread = mono_thread_current ();
4170                 thread->abort_exc = mono_get_exception_thread_abort ();        
4171                 mono_raise_exception (thread->abort_exc);
4172         } else
4173                 context->abort_thread = 1;
4174 }
4175
4176 static MonoBoolean
4177 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
4178                           MonoReflectionMethod **method, 
4179                           gint32 *iloffset, gint32 *native_offset,
4180                           MonoString **file, gint32 *line, gint32 *column)
4181 {
4182         ThreadContext *context = TlsGetValue (thread_context_id);
4183         MonoInvocation *inv = context->current_frame;
4184         int i;
4185
4186         for (i = 0; inv && i < skip; inv = inv->parent)
4187                 if (inv->runtime_method != NULL)
4188                         ++i;
4189
4190         if (iloffset)
4191                 *iloffset = 0;
4192         if (native_offset)
4193                 *native_offset = 0;
4194         if (method)
4195                 *method = inv == NULL ? NULL : mono_method_get_object (context->domain, inv->runtime_method->method, NULL);
4196         if (line)
4197                 *line = 0;
4198         if (need_file_info) {
4199                 if (column)
4200                         *column = 0;
4201                 if (file)
4202                         *file = mono_string_new (mono_domain_get (), "unknown");
4203         }
4204
4205         return TRUE;
4206 }
4207
4208 static MonoArray *
4209 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
4210 {
4211         MonoDomain *domain = mono_domain_get ();
4212         MonoArray *res;
4213         MonoArray *ta = exc->trace_ips;
4214         int i, len;
4215
4216         if (ta == NULL) {
4217                 /* Exception is not thrown yet */
4218                 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
4219         }
4220         
4221         len = mono_array_length (ta);
4222
4223         res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
4224
4225         for (i = skip; i < len / 2; i++) {
4226                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
4227                 gushort *ip = mono_array_get (ta, gpointer, 2 * i + 1);
4228                 RuntimeMethod *rtm = mono_array_get (ta, gpointer, 2 * i);
4229
4230                 if (rtm != NULL) {
4231                         sf->method = mono_method_get_object (domain, rtm->method, NULL);
4232                         sf->native_offset = ip - rtm->code;
4233                 }
4234
4235 #if 0
4236                 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
4237
4238                 if (need_file_info) {
4239                         gchar *filename;
4240                         
4241                         filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
4242
4243                         sf->filename = filename? mono_string_new (domain, filename): NULL;
4244                         sf->column = 0;
4245
4246                         g_free (filename);
4247                 }
4248 #endif
4249
4250                 mono_array_set (res, gpointer, i, sf);
4251         }
4252
4253         return res;
4254 }
4255
4256 static MonoObject *
4257 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
4258                                                    MonoReflectionMethod *info)
4259 {
4260         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
4261         MonoObject *delegate;
4262
4263         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
4264
4265         delegate = mono_object_new (mono_object_domain (type), delegate_class);
4266
4267         interp_delegate_ctor (mono_object_domain (type), delegate, target, mono_interp_get_runtime_method (info->method));
4268
4269         return delegate;
4270 }
4271
4272
4273 typedef struct
4274 {
4275         MonoDomain *domain;
4276         int enable_debugging;
4277         char *file;
4278         int argc;
4279         char **argv;
4280 } MainThreadArgs;
4281
4282 static void main_thread_handler (gpointer user_data)
4283 {
4284         MainThreadArgs *main_args=(MainThreadArgs *)user_data;
4285         MonoAssembly *assembly;
4286
4287         if (main_args->enable_debugging)
4288                 mono_debug_init (main_args->domain, MONO_DEBUG_FORMAT_MONO);
4289
4290         assembly = mono_domain_assembly_open (main_args->domain,
4291                                               main_args->file);
4292
4293         if (!assembly){
4294                 fprintf (stderr, "Can not open image %s\n", main_args->file);
4295                 exit (1);
4296         }
4297
4298         if (main_args->enable_debugging)
4299                 mono_debug_init_2 (assembly);
4300
4301 #ifdef RUN_TEST
4302         test_load_class (assembly->image);
4303 #else
4304
4305         ves_exec (main_args->domain, assembly, main_args->argc, main_args->argv);
4306 #endif
4307 }
4308
4309 static void
4310 mono_runtime_install_handlers (void)
4311 {
4312         add_signal_handler (SIGSEGV, segv_handler);
4313         add_signal_handler (SIGINT, quit_handler);
4314         add_signal_handler (SIGABRT, abrt_handler);
4315         add_signal_handler (mono_thread_get_abort_signal (), thread_abort_handler);
4316 }
4317
4318 static void
4319 quit_function (MonoDomain *domain, gpointer user_data)
4320 {
4321         mono_profiler_shutdown ();
4322         
4323         mono_runtime_cleanup (domain);
4324         mono_domain_free (domain, TRUE);
4325
4326 }
4327
4328 void
4329 mono_interp_cleanup(MonoDomain *domain)
4330 {
4331         quit_function (domain, NULL);
4332 }
4333
4334 int
4335 mono_interp_exec(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4336 {
4337         return ves_exec (domain, assembly, argc, argv);
4338 }
4339
4340 MonoDomain *
4341 mono_interp_init(const char *file)
4342 {
4343         MonoDomain *domain;
4344
4345         g_set_prgname (file);
4346         mono_set_rootdir ();
4347         
4348         g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
4349         g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
4350
4351         g_thread_init (NULL);
4352
4353         thread_context_id = TlsAlloc ();
4354         TlsSetValue (thread_context_id, NULL);
4355         InitializeCriticalSection (&runtime_method_lookup_section);
4356         InitializeCriticalSection (&create_method_pointer_mutex);
4357
4358         mono_runtime_install_handlers ();
4359         mono_interp_transform_init ();
4360         mono_install_compile_method (mono_create_method_pointer);
4361         mono_install_runtime_invoke (interp_mono_runtime_invoke);
4362         mono_install_remoting_trampoline (interp_create_remoting_trampoline);
4363         mono_install_trampoline (interp_create_trampoline);
4364
4365         mono_install_handler (interp_ex_handler);
4366         mono_install_stack_walk (interp_walk_stack);
4367         mono_runtime_install_cleanup (quit_function);
4368
4369         domain = mono_init (file);
4370 #ifdef __hpux /* generates very big stack frames */
4371         mono_threads_set_default_stacksize(32*1024*1024);
4372 #endif
4373         mono_init_icall ();
4374         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", ves_icall_get_frame_info);
4375         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", ves_icall_get_trace);
4376         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
4377         mono_add_internal_call ("System.Delegate::CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal);
4378
4379         mono_runtime_init (domain, NULL, NULL);
4380
4381         return domain;
4382 }
4383
4384 int 
4385 mono_main (int argc, char *argv [])
4386 {
4387         MonoDomain *domain;
4388         int retval = 0, i;
4389         char *file, *config_file = NULL;
4390         int enable_debugging = FALSE;
4391         MainThreadArgs main_args;
4392         const char *error;
4393
4394         setlocale (LC_ALL, "");
4395         if (argc < 2)
4396                 usage ();
4397
4398         for (i = 1; i < argc && argv [i][0] == '-'; i++){
4399                 if (strcmp (argv [i], "--trace") == 0)
4400                         global_tracing = 1;
4401                 if (strcmp (argv [i], "--noptr") == 0)
4402                         global_no_pointers = 1;
4403                 if (strcmp (argv [i], "--traceops") == 0)
4404                         global_tracing = 2;
4405                 if (strcmp (argv [i], "--traceopt") == 0)
4406                         ++mono_interp_traceopt;
4407                 if (strcmp (argv [i], "--dieonex") == 0) {
4408                         die_on_exception = 1;
4409                         enable_debugging = 1;
4410                 }
4411                 if (strcmp (argv [i], "--print-vtable") == 0)
4412                         mono_print_vtable = TRUE;
4413                 if (strcmp (argv [i], "--profile") == 0)
4414                         mono_profiler_load (NULL);
4415                 if (strcmp (argv [i], "--config") == 0)
4416                         config_file = argv [++i];
4417                 if (strcmp (argv [i], "--workers") == 0) {
4418                         mono_max_worker_threads = atoi (argv [++i]);
4419                         if (mono_max_worker_threads < 1)
4420                                 mono_max_worker_threads = 1;
4421                 }
4422                 if (strcmp (argv [i], "--help") == 0)
4423                         usage ();
4424 #if DEBUG_INTERP
4425                 if (strcmp (argv [i], "--debug") == 0) {
4426                         MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
4427                         if (!desc)
4428                                 g_error ("Invalid method name '%s'", argv [i]);
4429                         db_methods = g_list_append (db_methods, desc);
4430                 }
4431                 if (strcmp (argv [i], "--nested") == 0)
4432                         nested_trace = 1;
4433 #endif
4434         }
4435         
4436         file = argv [i];
4437
4438         if (!file)
4439                 usage ();
4440
4441         domain = mono_interp_init(file);
4442         mono_config_parse (config_file);
4443
4444         error = mono_check_corlib_version ();
4445         if (error) {
4446                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
4447                 fprintf (stderr, "Download a newer corlib at http://www.go-mono.com/daily.\n");
4448                 exit (1);
4449         }
4450
4451         main_args.domain=domain;
4452         main_args.file=file;
4453         main_args.argc=argc-i;
4454         main_args.argv=argv+i;
4455         main_args.enable_debugging=enable_debugging;
4456         
4457         mono_runtime_exec_managed_code (domain, main_thread_handler,
4458                                         &main_args);
4459
4460         quit_function (domain, NULL);
4461
4462         /* Get the return value from System.Environment.ExitCode */
4463         retval=mono_environment_exitcode_get ();
4464
4465 #if COUNT_OPS
4466         for (i = 0; i < 512; i++)
4467                 if (opcode_counts[i] != 0)
4468                         printf("%s %d\n", mono_interp_opname[i], opcode_counts[i]);
4469 #endif
4470         return retval;
4471 }