2003-10-13 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
26 #include <mono/os/gc_wrapper.h>
27
28 #ifdef HAVE_ALLOCA_H
29 #   include <alloca.h>
30 #else
31 #   ifdef __CYGWIN__
32 #      define alloca __builtin_alloca
33 #   endif
34 #endif
35
36 /* trim excessive headers */
37 #include <mono/metadata/image.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/cil-coff.h>
40 #include <mono/metadata/mono-endian.h>
41 #include <mono/metadata/tabledefs.h>
42 #include <mono/metadata/blob.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/io-layer/io-layer.h>
55 #include <mono/metadata/socket-io.h>
56 #include <mono/metadata/mono-config.h>
57 #include <mono/metadata/marshal.h>
58 #include <mono/metadata/environment.h>
59 #include <mono/metadata/mono-debug.h>
60 #include <mono/os/util.h>
61
62 /*#include <mono/cli/types.h>*/
63 #include "interp.h"
64 #include "hacks.h"
65
66 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
67 #ifdef _WIN32
68 #define isnan _isnan
69 #define finite _finite
70 #endif
71 #ifndef HAVE_FINITE
72 #ifdef HAVE_ISFINITE
73 #define finite isfinite
74 #endif
75 #endif
76
77 /* If true, then we output the opcodes as we interpret them */
78 static int global_tracing = 0;
79 static int global_no_pointers = 0;
80
81 static int debug_indent_level = 0;
82
83 /*
84  * Pull the list of opcodes
85  */
86 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
87         a = i,
88
89 enum {
90 #include "mono/cil/opcode.def"
91         LAST = 0xff
92 };
93 #undef OPDEF
94
95 #if SIZEOF_VOID_P == 8
96 #define GET_NATI(sp) ((sp).type == VAL_I32 ? (sp).data.i : (sp).data.nati)
97 #else
98 #define GET_NATI(sp) (sp).data.i
99 #endif
100 #define CSIZE(x) (sizeof (x) / 4)
101
102 #define INIT_FRAME(frame,parent_frame,obj_this,method_args,method_retval,mono_method)   \
103         do {    \
104                 (frame)->parent = (parent_frame);       \
105                 (frame)->obj = (obj_this);      \
106                 (frame)->stack_args = (method_args);    \
107                 (frame)->retval = (method_retval);      \
108                 (frame)->method = (mono_method);        \
109                 (frame)->ex_handler = NULL;     \
110                 (frame)->ex = NULL;     \
111                 (frame)->child = NULL;  \
112                 (frame)->ip = NULL;     \
113                 (frame)->invoke_trap = 0;       \
114         } while (0)
115
116 typedef struct {
117         MonoInvocation *base_frame;
118         MonoInvocation *current_frame;
119         MonoInvocation *env_frame;
120         jmp_buf *current_env;
121         int search_for_handler;
122 } ThreadContext;
123
124 static MonoException * quit_exception = NULL;
125
126 void ves_exec_method (MonoInvocation *frame);
127
128 static char* dump_stack (stackval *stack, stackval *sp);
129 static char* dump_frame (MonoInvocation *inv);
130 static void ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
131
132 typedef void (*ICallMethod) (MonoInvocation *frame);
133
134 static guint32 die_on_exception = 0;
135 static guint32 thread_context_id = 0;
136
137 #define DEBUG_INTERP 1
138 #if DEBUG_INTERP
139
140 static unsigned long opcode_count = 0;
141 static unsigned long fcall_count = 0;
142 static int break_on_method = 0;
143 static GList *db_methods = NULL;
144
145 static void
146 output_indent (void)
147 {
148         int h;
149
150         for (h = 0; h < debug_indent_level; h++)
151                 g_print ("  ");
152 }
153
154 static void
155 db_match_method (gpointer data, gpointer user_data)
156 {
157         MonoMethod *m = (MonoMethod*)user_data;
158         MonoMethodDesc *desc = data;
159
160         if (mono_method_desc_full_match (desc, m))
161                 break_on_method = 1;
162 }
163
164 #define DEBUG_ENTER()   \
165         fcall_count++;  \
166         g_list_foreach (db_methods, db_match_method, (gpointer)frame->method);  \
167         if (break_on_method) tracing=2; \
168         break_on_method = 0;    \
169         if (tracing) {  \
170                 char *mn, *args = dump_stack (frame->stack_args, frame->stack_args+signature->param_count);     \
171                 debug_indent_level++;   \
172                 output_indent ();       \
173                 mn = mono_method_full_name (frame->method, FALSE); \
174                 g_print ("(%u) Entering %s (", GetCurrentThreadId(), mn);       \
175                 g_free (mn); \
176                 if (signature->hasthis) { \
177                         if (global_no_pointers) { \
178                                 g_print ("this%s ", frame->obj ? "" : "=null"); \
179                         } else { \
180                                 g_print ("%p ", frame->obj); } \
181                 } \
182                 g_print ("%s)\n", args);        \
183                 g_free (args);  \
184         }       \
185         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
186                 mono_profiler_method_enter (frame->method);
187
188 #define DEBUG_LEAVE()   \
189         if (tracing) {  \
190                 char *mn, *args;        \
191                 if (signature->ret->type != MONO_TYPE_VOID)     \
192                         args = dump_stack (frame->retval, frame->retval + 1);   \
193                 else    \
194                         args = g_strdup ("");   \
195                 output_indent ();       \
196                 mn = mono_method_full_name (frame->method, FALSE); \
197                 g_print ("(%u) Leaving %s", GetCurrentThreadId(),  mn); \
198                 g_free (mn); \
199                 g_print (" => %s\n", args);     \
200                 g_free (args);  \
201                 debug_indent_level--;   \
202         }       \
203         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
204                 mono_profiler_method_leave (frame->method);
205
206 #else
207
208 #define DEBUG_ENTER()
209 #define DEBUG_LEAVE()
210
211 #endif
212
213 static void
214 interp_ex_handler (MonoException *ex) {
215         ThreadContext *context = TlsGetValue (thread_context_id);
216         char *stack_trace;
217         stack_trace = dump_frame (context->current_frame);
218         ex->stack_trace = mono_string_new (mono_domain_get(), stack_trace);
219         g_free (stack_trace);
220         if (context == NULL || context->current_env == NULL) {
221                 char *strace = mono_string_to_utf8 (ex->stack_trace);
222                 fprintf(stderr, "Nothing can catch this exception: ");
223                 fprintf(stderr, "%s", ex->object.vtable->klass->name);
224                 if (ex->message != NULL) {
225                         char *m = mono_string_to_utf8 (ex->message);
226                         fprintf(stderr, ": %s", m);
227                         g_free(m);
228                 }
229                 fprintf(stderr, "\n");
230                 fprintf(stderr, "%s\n", strace);
231                 g_free (strace);
232                 if (ex->inner_ex != NULL) {
233                         ex = (MonoException *)ex->inner_ex;
234                         fprintf(stderr, "Inner exception: %s", ex->object.vtable->klass->name);
235                         if (ex->message != NULL) {
236                                 char *m = mono_string_to_utf8 (ex->message);
237                                 fprintf(stderr, ": %s", m);
238                                 g_free(m);
239                         }
240                         strace = mono_string_to_utf8 (ex->stack_trace);
241                         fprintf(stderr, "\n");
242                         fprintf(stderr, "%s\n", strace);
243                         g_free (strace);
244                 }
245                 exit(1);
246         }
247         context->env_frame->ex = ex;
248         context->search_for_handler = 1;
249         longjmp (*context->current_env, 1);
250 }
251
252 static void
253 ves_real_abort (int line, MonoMethod *mh,
254                 const unsigned char *ip, stackval *stack, stackval *sp)
255 {
256         MonoMethodNormal *mm = (MonoMethodNormal *)mh;
257         fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
258         fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
259                  ip-mm->header->code);
260         g_print ("0x%04x %02x\n",
261                  ip-mm->header->code, *ip);
262         if (sp > stack)
263                 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
264 }
265 #define ves_abort() do {ves_real_abort(__LINE__, frame->method, ip, frame->stack, sp); THROW_EX (mono_get_exception_execution_engine (NULL), ip);} while (0);
266
267 static gpointer
268 interp_create_remoting_trampoline (MonoMethod *method)
269 {
270         return mono_marshal_get_remoting_invoke (method);
271 }
272
273 static MonoMethod*
274 get_virtual_method (MonoDomain *domain, MonoMethod *m, stackval *objs)
275 {
276         MonoObject *obj;
277         MonoClass *klass;
278         MonoMethod **vtable;
279         gboolean is_proxy = FALSE;
280         MonoMethod *res;
281
282         if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL))
283                         return m;
284
285         obj = objs->data.p;
286         if ((klass = obj->vtable->klass) == mono_defaults.transparent_proxy_class) {
287                 klass = ((MonoTransparentProxy *)obj)->klass;
288                 is_proxy = TRUE;
289         }
290         vtable = (MonoMethod **)klass->vtable;
291
292         if (m->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
293                 res = ((MonoMethod **)obj->vtable->interface_offsets [m->klass->interface_id]) [m->slot];
294         } else {
295                 res = vtable [m->slot];
296         }
297         g_assert (res);
298
299         if (is_proxy)
300                 return mono_marshal_get_remoting_invoke (res);
301         
302         return res;
303 }
304
305 void inline
306 stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke)
307 {
308         if (type->byref) {
309                 switch (type->type) {
310                 case MONO_TYPE_OBJECT:
311                 case MONO_TYPE_CLASS:
312                 case MONO_TYPE_STRING:
313                 case MONO_TYPE_ARRAY:
314                 case MONO_TYPE_SZARRAY:
315                         result->type = VAL_OBJ;
316                         break;
317                 default:
318                         result->type = VAL_MP;
319                         break;
320                 }
321                 result->data.p = *(gpointer*)data;
322                 return;
323         }
324         switch (type->type) {
325         case MONO_TYPE_VOID:
326                 return;
327         case MONO_TYPE_I1:
328                 result->type = VAL_I32;
329                 result->data.i = *(gint8*)data;
330                 return;
331         case MONO_TYPE_U1:
332         case MONO_TYPE_BOOLEAN:
333                 result->type = VAL_I32;
334                 result->data.i = *(guint8*)data;
335                 return;
336         case MONO_TYPE_I2:
337                 result->type = VAL_I32;
338                 result->data.i = *(gint16*)data;
339                 return;
340         case MONO_TYPE_U2:
341         case MONO_TYPE_CHAR:
342                 result->type = VAL_I32;
343                 result->data.i = *(guint16*)data;
344                 return;
345         case MONO_TYPE_I4:
346                 result->type = VAL_I32;
347                 result->data.i = *(gint32*)data;
348                 return;
349         case MONO_TYPE_U:
350         case MONO_TYPE_I:
351                 result->type = VAL_NATI;
352                 result->data.nati = *(mono_i*)data;
353                 return;
354         case MONO_TYPE_PTR:
355                 result->type = VAL_TP;
356                 result->data.p = *(gpointer*)data;
357                 return;
358         case MONO_TYPE_U4:
359                 result->type = VAL_I32;
360                 result->data.i = *(guint32*)data;
361                 return;
362         case MONO_TYPE_R4:
363                 result->type = VAL_DOUBLE;
364                 result->data.f = *(float*)data;
365                 return;
366         case MONO_TYPE_I8:
367         case MONO_TYPE_U8:
368                 result->type = VAL_I64;
369                 result->data.l = *(gint64*)data;
370                 return;
371         case MONO_TYPE_R8:
372                 result->type = VAL_DOUBLE;
373                 result->data.f = *(double*)data;
374                 return;
375         case MONO_TYPE_STRING:
376         case MONO_TYPE_SZARRAY:
377         case MONO_TYPE_CLASS:
378         case MONO_TYPE_OBJECT:
379         case MONO_TYPE_ARRAY:
380                 result->type = VAL_OBJ;
381                 result->data.p = *(gpointer*)data;
382                 return;
383         case MONO_TYPE_VALUETYPE:
384                 if (type->data.klass->enumtype) {
385                         stackval_from_data (type->data.klass->enum_basetype, result, data, pinvoke);
386                         return;
387                 } else {
388                         int size;
389                         result->type = VAL_VALUET;
390                         
391                         if (pinvoke)
392                                 size = mono_class_native_size (type->data.klass, NULL);
393                         else
394                                 size = mono_class_value_size (type->data.klass, NULL);
395                         memcpy (result->data.vt, data, size);
396                 }
397                 return;
398         default:
399                 g_warning ("got type 0x%02x", type->type);
400                 g_assert_not_reached ();
401         }
402 }
403
404 void inline
405 stackval_to_data (MonoType *type, stackval *val, char *data, gboolean pinvoke)
406 {
407         if (type->byref) {
408                 gpointer *p = (gpointer*)data;
409                 *p = val->data.p;
410                 return;
411         }
412         //printf ("TODAT0 %p\n", data);
413         switch (type->type) {
414         case MONO_TYPE_I1:
415         case MONO_TYPE_U1: {
416                 guint8 *p = (guint8*)data;
417                 *p = val->data.i;
418                 return;
419         }
420         case MONO_TYPE_BOOLEAN: {
421                 guint8 *p = (guint8*)data;
422                 *p = (val->data.i != 0);
423                 return;
424         }
425         case MONO_TYPE_I2:
426         case MONO_TYPE_U2:
427         case MONO_TYPE_CHAR: {
428                 guint16 *p = (guint16*)data;
429                 *p = val->data.i;
430                 return;
431         }
432         case MONO_TYPE_I: {
433                 mono_i *p = (mono_i*)data;
434                 /* In theory the value used by stloc should match the local var type
435                    but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
436                    a native int - both by csc and mcs). Not sure what to do about sign extension
437                    as it is outside the spec... doing the obvious */
438                 *p = val->type == VAL_I32 ? val->data.i : val->data.nati;
439                 return;
440         }
441         case MONO_TYPE_U: {
442                 mono_u *p = (mono_u*)data;
443                 /* see above. */
444                 *p = val->type == VAL_I32 ? (guint32)val->data.i : val->data.nati;
445                 return;
446         }
447         case MONO_TYPE_I4:
448         case MONO_TYPE_U4: {
449                 gint32 *p = (gint32*)data;
450                 *p = val->data.i;
451                 return;
452         }
453         case MONO_TYPE_I8:
454         case MONO_TYPE_U8: {
455                 gint64 *p = (gint64*)data;
456                 *p = val->data.l;
457                 return;
458         }
459         case MONO_TYPE_R4: {
460                 float *p = (float*)data;
461                 *p = val->data.f;
462                 return;
463         }
464         case MONO_TYPE_R8: {
465                 double *p = (double*)data;
466                 *p = val->data.f;
467                 return;
468         }
469         case MONO_TYPE_STRING:
470         case MONO_TYPE_SZARRAY:
471         case MONO_TYPE_CLASS:
472         case MONO_TYPE_OBJECT:
473         case MONO_TYPE_ARRAY:
474         case MONO_TYPE_PTR: {
475                 gpointer *p = (gpointer*)data;
476                 *p = val->data.p;
477                 return;
478         }
479         case MONO_TYPE_VALUETYPE:
480                 if (type->data.klass->enumtype) {
481                         stackval_to_data (type->data.klass->enum_basetype, val, data, pinvoke);
482                         return;
483                 } else {
484                         int size;
485
486                         if (pinvoke)
487                                 size = mono_class_native_size (type->data.klass, NULL);
488                         else
489                                 size = mono_class_value_size (type->data.klass, NULL);
490
491                         memcpy (data, val->data.vt, size);
492                 }
493                 return;
494         default:
495                 g_warning ("got type %x", type->type);
496                 g_assert_not_reached ();
497         }
498 }
499
500 #define FILL_IN_TRACE(exception, frame) \
501         do { \
502                 char *stack_trace;      \
503                 stack_trace = dump_frame (frame);       \
504                 (exception)->stack_trace = mono_string_new (mono_domain_get(), stack_trace);    \
505                 g_free (stack_trace);   \
506         } while (0)
507
508 #define THROW_EX(exception,ex_ip)       \
509         do {\
510                 frame->ip = (ex_ip);            \
511                 frame->ex = (MonoException*)(exception);        \
512                 FILL_IN_TRACE(frame->ex, frame); \
513                 goto handle_exception;  \
514         } while (0)
515
516 static MonoObject*
517 ves_array_create (MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
518 {
519         guint32 *lengths;
520         guint32 *lower_bounds;
521         int i;
522
523         lengths = alloca (sizeof (guint32) * klass->rank * 2);
524         for (i = 0; i < sig->param_count; ++i) {
525                 lengths [i] = values->data.i;
526                 values ++;
527         }
528         if (klass->rank == sig->param_count) {
529                 /* Only lengths provided. */
530                 lower_bounds = NULL;
531         } else {
532                 /* lower bounds are first. */
533                 lower_bounds = lengths;
534                 lengths += klass->rank;
535         }
536         return (MonoObject*)mono_array_new_full (domain, klass, lengths, lower_bounds);
537 }
538
539 static void 
540 ves_array_set (MonoInvocation *frame)
541 {
542         stackval *sp = frame->stack_args;
543         MonoObject *o;
544         MonoArray *ao;
545         MonoClass *ac;
546         gint32 i, t, pos, esize;
547         gpointer ea;
548         MonoType *mt;
549
550         o = frame->obj;
551         ao = (MonoArray *)o;
552         ac = o->vtable->klass;
553
554         g_assert (ac->rank >= 1);
555
556         pos = sp [0].data.i;
557         if (ao->bounds != NULL) {
558                 pos -= ao->bounds [0].lower_bound;
559                 for (i = 1; i < ac->rank; i++) {
560                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
561                             ao->bounds [i].length) {
562                                 frame->ex = mono_get_exception_index_out_of_range ();
563                                 FILL_IN_TRACE(frame->ex, frame);
564                                 return;
565                         }
566                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
567                                 ao->bounds [i].lower_bound;
568                 }
569         } else if (pos >= ao->max_length) {
570                 frame->ex = mono_get_exception_index_out_of_range ();
571                 FILL_IN_TRACE(frame->ex, frame);
572                 return;
573         }
574
575         esize = mono_array_element_size (ac);
576         ea = mono_array_addr_with_size (ao, esize, pos);
577
578         mt = frame->method->signature->params [ac->rank];
579         stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
580 }
581
582 static void 
583 ves_array_get (MonoInvocation *frame)
584 {
585         stackval *sp = frame->stack_args;
586         MonoObject *o;
587         MonoArray *ao;
588         MonoClass *ac;
589         gint32 i, t, pos, esize;
590         gpointer ea;
591         MonoType *mt;
592
593         o = frame->obj;
594         ao = (MonoArray *)o;
595         ac = o->vtable->klass;
596
597         g_assert (ac->rank >= 1);
598
599         pos = sp [0].data.i;
600         if (ao->bounds != NULL) {
601                 pos -= ao->bounds [0].lower_bound;
602                 for (i = 1; i < ac->rank; i++) {
603                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
604                             ao->bounds [i].length) {
605                                 frame->ex = mono_get_exception_index_out_of_range ();
606                                 FILL_IN_TRACE(frame->ex, frame);
607                                 return;
608                         }
609
610                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
611                                 ao->bounds [i].lower_bound;
612                 }
613         } else if (pos >= ao->max_length) {
614                 frame->ex = mono_get_exception_index_out_of_range ();
615                 FILL_IN_TRACE(frame->ex, frame);
616                 return;
617         }
618
619         esize = mono_array_element_size (ac);
620         ea = mono_array_addr_with_size (ao, esize, pos);
621
622         mt = frame->method->signature->ret;
623         stackval_from_data (mt, frame->retval, ea, FALSE);
624 }
625
626 static void
627 ves_array_element_address (MonoInvocation *frame)
628 {
629         stackval *sp = frame->stack_args;
630         MonoObject *o;
631         MonoArray *ao;
632         MonoClass *ac;
633         gint32 i, t, pos, esize;
634         gpointer ea;
635
636         o = frame->obj;
637         ao = (MonoArray *)o;
638         ac = o->vtable->klass;
639
640         g_assert (ac->rank >= 1);
641
642         pos = sp [0].data.i;
643         if (ao->bounds != NULL) {
644                 pos -= ao->bounds [0].lower_bound;
645                 for (i = 1; i < ac->rank; i++) {
646                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
647                             ao->bounds [i].length) {
648                                 frame->ex = mono_get_exception_index_out_of_range ();
649                                 FILL_IN_TRACE(frame->ex, frame);
650                                 return;
651                         }
652                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
653                                 ao->bounds [i].lower_bound;
654                 }
655         } else if (pos >= ao->max_length) {
656                 frame->ex = mono_get_exception_index_out_of_range ();
657                 FILL_IN_TRACE(frame->ex, frame);
658                 return;
659         }
660
661         esize = mono_array_element_size (ac);
662         ea = mono_array_addr_with_size (ao, esize, pos);
663
664         frame->retval->type = VAL_MP;
665         frame->retval->data.p = ea;
666 }
667
668 static void
669 interp_walk_stack (MonoStackWalk func, gpointer user_data)
670 {
671         ThreadContext *context = TlsGetValue (thread_context_id);
672         MonoInvocation *frame = context->current_frame;
673         int il_offset;
674         MonoMethodHeader *hd;
675
676         while (frame) {
677                 gboolean managed = FALSE;
678                 if (!frame->method || (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || 
679                                 (frame->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
680                         il_offset = -1;
681                 else {
682                         hd = ((MonoMethodNormal*)frame->method)->header;
683                         il_offset = frame->ip - hd->code;
684                         if (!frame->method->wrapper_type)
685                                 managed = TRUE;
686                 }
687                 if (func (frame->method, -1, il_offset, managed, user_data))
688                         return;
689                 frame = frame->parent;
690         }
691 }
692
693 static void 
694 ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFunc addr, gboolean string_ctor, ThreadContext *context)
695 {
696         jmp_buf env;
697         MonoPIFunc func;
698         MonoInvocation *old_frame = context->current_frame;
699         MonoInvocation *old_env_frame = context->env_frame;
700         jmp_buf *old_env = context->current_env;
701
702         if (setjmp (env)) {
703                 context->current_frame = old_frame;
704                 context->env_frame = old_env_frame;
705                 context->current_env = old_env;
706                 context->search_for_handler = 0;
707                 return;
708         }
709
710         context->env_frame = frame;
711         context->current_env = &env;
712
713         if (frame->method) {
714                 if (!frame->method->info) {
715                         func = frame->method->info = mono_create_trampoline (sig, string_ctor);
716                 } else { 
717                         func = (MonoPIFunc)frame->method->info;
718                 }
719         } else {
720                 func = mono_create_trampoline (sig, string_ctor);
721         }
722
723         context->current_frame = frame;
724
725         func (addr, &frame->retval->data.p, frame->obj, frame->stack_args);
726
727         if (string_ctor) {
728                 stackval_from_data (&mono_defaults.string_class->byval_arg, 
729                                     frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
730         } else if (!MONO_TYPE_ISSTRUCT (sig->ret))
731                 stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
732
733         context->current_frame = old_frame;
734         context->env_frame = old_env_frame;
735         context->current_env = old_env;
736 }
737
738 /*
739  * From the spec:
740  * runtime specifies that the implementation of the method is automatically
741  * provided by the runtime and is primarily used for the methods of delegates.
742  */
743 static void
744 ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
745 {
746         const char *name = frame->method->name;
747         MonoObject *obj = (MonoObject*)frame->obj;
748         MonoInvocation call;
749         MonoMethod *nm;
750
751
752         mono_class_init (frame->method->klass);
753         
754         if (obj && mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
755                 if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
756                         mono_delegate_ctor (obj, frame->stack_args[0].data.p, frame->stack_args[1].data.p);
757                         return;
758                 }
759                 if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
760                         nm = mono_marshal_get_delegate_invoke (frame->method);
761                         INIT_FRAME(&call,frame,obj,frame->stack_args,frame->retval,nm);
762                         ves_exec_method_with_context (&call, context);
763                         frame->ex = call.ex;
764                         return;
765                 }
766                 if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
767                         nm = mono_marshal_get_delegate_begin_invoke (frame->method);
768                         INIT_FRAME(&call,frame,obj,frame->stack_args,frame->retval,nm);
769                         ves_exec_method_with_context (&call, context);
770                         frame->ex = call.ex;
771                         return;
772                 }
773                 if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
774                         nm = mono_marshal_get_delegate_end_invoke (frame->method);
775                         INIT_FRAME(&call,frame,obj,frame->stack_args,frame->retval,nm);
776                         ves_exec_method_with_context (&call, context);
777                         frame->ex = call.ex;
778                         return;
779                 }
780         }
781
782         if (obj && mono_object_isinst (obj, mono_defaults.array_class)) {
783                 if (*name == 'S' && (strcmp (name, "Set") == 0)) {
784                         ves_array_set (frame);
785                         return;
786                 }
787                 if (*name == 'G' && (strcmp (name, "Get") == 0)) {
788                         ves_array_get (frame);
789                         return;
790                 }
791                 if (*name == 'A' && (strcmp (name, "Address") == 0)) {
792                         ves_array_element_address (frame);
793                         return;
794                 }
795         }
796         
797         g_error ("Don't know how to exec runtime method %s.%s::%s", 
798                         frame->method->klass->name_space, frame->method->klass->name,
799                         frame->method->name);
800 }
801
802 static char*
803 dump_stack (stackval *stack, stackval *sp)
804 {
805         stackval *s = stack;
806         GString *str = g_string_new ("");
807         
808         if (sp == stack)
809                 return g_string_free (str, FALSE);
810         
811         while (s < sp) {
812                 switch (s->type) {
813 #if SIZEOF_VOID_P == 4
814                 case VAL_NATI: g_string_sprintfa (str, "[%d/0x%0x] ", s->data.nati, s->data.nati); break;
815 #else
816                 case VAL_NATI: g_string_sprintfa (str, "[%lld/0x%0llx] ", s->data.nati, s->data.nati); break;
817 #endif
818                 case VAL_I32: g_string_sprintfa (str, "[%d] ", s->data.i); break;
819                 case VAL_I64: g_string_sprintfa (str, "[%lldL] ", s->data.l); break;
820                 case VAL_DOUBLE: g_string_sprintfa (str, "[%0.5f] ", s->data.f); break;
821                 case VAL_VALUET:
822                         if (!global_no_pointers)
823                                 g_string_sprintfa (str, "[vt: %p] ", s->data.vt);
824                         else
825                                 g_string_sprintfa (str, "[vt%s] ", s->data.vt ? "" : "=null");
826                         break;
827                 case VAL_OBJ: {
828                         MonoObject *obj =  s->data.p;
829                         if (global_no_pointers && obj && obj->vtable) {
830                                 MonoClass *klass = mono_object_class (obj);
831                                 if (klass == mono_defaults.string_class) {
832                                         char *utf8 = mono_string_to_utf8 ((MonoString*) obj);
833                                         g_string_sprintfa (str, "[str:%s] ", utf8);
834                                         g_free (utf8);
835                                         break;
836                                 } else if (klass == mono_defaults.sbyte_class) {
837                                         g_string_sprintfa (str, "[b:%d] ",
838                                                            *(gint8 *)((guint8 *) obj + sizeof (MonoObject)));
839                                         break;
840                                 } else if (klass == mono_defaults.int16_class) {
841                                         g_string_sprintfa (str, "[b:%d] ",
842                                                            *(gint16 *)((guint8 *) obj + sizeof (MonoObject)));
843                                         break;
844                                 } else if (klass == mono_defaults.int32_class) {
845                                         g_string_sprintfa (str, "[b:%d] ",
846                                                            *(gint32 *)((guint8 *) obj + sizeof (MonoObject)));
847                                         break;
848                                 } else if (klass == mono_defaults.byte_class) {
849                                         g_string_sprintfa (str, "[b:%u] ",
850                                                            *(guint8 *)((guint8 *) obj + sizeof (MonoObject)));
851                                         break;
852                                 } else if (klass == mono_defaults.char_class
853                                            || klass == mono_defaults.uint16_class) {
854                                         g_string_sprintfa (str, "[b:%u] ",
855                                                            *(guint16 *)((guint8 *) obj + sizeof (MonoObject)));
856                                         break;
857                                 } else if (klass == mono_defaults.uint32_class) {
858                                         g_string_sprintfa (str, "[b:%u] ",
859                                                            *(guint32 *)((guint8 *) obj + sizeof (MonoObject)));
860                                         break;
861                                 } else if (klass == mono_defaults.int64_class) {
862                                         g_string_sprintfa (str, "[b:%lld] ",
863                                                            *(gint64 *)((guint8 *) obj + sizeof (MonoObject)));
864                                         break;
865                                 } else if (klass == mono_defaults.uint64_class) {
866                                         g_string_sprintfa (str, "[b:%llu] ",
867                                                            *(guint64 *)((guint8 *) obj + sizeof (MonoObject)));
868                                         break;
869                                 } else if (klass == mono_defaults.double_class) {
870                                         g_string_sprintfa (str, "[b:%0.5f] ",
871                                                            *(gdouble *)((guint8 *) obj + sizeof (MonoObject)));
872                                         break;
873                                 } else if (klass == mono_defaults.single_class) {
874                                         g_string_sprintfa (str, "[b:%0.5f] ",
875                                                            *(gfloat *)((guint8 *) obj + sizeof (MonoObject)));
876                                         break;
877                                 } else if (klass == mono_defaults.boolean_class) {
878                                         g_string_sprintfa (str, "[b:%s] ",
879                                                            *(gboolean *)((guint8 *) obj + sizeof (MonoObject))
880                                                            ? "true" : "false");
881                                         break;
882                                 }
883                         }
884                         /* fall thru */
885                 }
886                 default:
887                         if (!global_no_pointers)
888                                 g_string_sprintfa (str, "[%c:%p] ", s->type == VAL_OBJ ? 'O' : s->type == VAL_MP ? 'M' : '?', s->data.p);
889                         else
890                                 g_string_sprintfa (str, s->data.p ? "[ptr] " : "[null] ");
891                         break;
892                 }
893                 ++s;
894         }
895         return g_string_free (str, FALSE);
896 }
897
898 static char*
899 dump_frame (MonoInvocation *inv)
900 {
901         GString *str = g_string_new ("");
902         int i;
903         char *args;
904         for (i = 0; inv; inv = inv->parent, ++i) {
905                 if (inv->method != NULL) {
906                         MonoClass *k;
907
908                         int codep = 0;
909                         const char * opname = "";
910                         gchar *source = NULL;
911
912                         if (!inv->method) {
913                                 --i;
914                                 continue;
915                         }
916
917                         k = inv->method->klass;
918
919                         if ((inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
920                                 (inv->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
921                                 MonoMethodHeader *hd = ((MonoMethodNormal *)inv->method)->header;
922
923                                 if (hd != NULL) {
924                                         if (inv->ip)
925                                                 codep = *(inv->ip) == 0xfe? inv->ip [1] + 256: *(inv->ip);
926                                         else
927                                                 codep = 0;
928                                         opname = mono_opcode_names [codep];
929                                         codep = inv->ip - hd->code;
930         
931                                         source = mono_debug_source_location_from_il_offset (inv->method, codep, NULL);
932                                 }
933                         }
934                         args = dump_stack (inv->stack_args, inv->stack_args + inv->method->signature->param_count);
935                         if (source)
936                                 g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s.%s::%s (%s) at %s\n", i, codep, opname,
937                                                    k->name_space, k->name, inv->method->name, args, source);
938                         else
939                                 g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s.%s::%s (%s)\n", i, codep, opname,
940                                                    k->name_space, k->name, inv->method->name, args);
941                         g_free (args);
942                         g_free (source);
943                 }
944         }
945         return g_string_free (str, FALSE);
946 }
947
948 typedef enum {
949         INLINE_STRING_LENGTH = 1,
950         INLINE_STRING_GET_CHARS,
951         INLINE_ARRAY_LENGTH,
952         INLINE_ARRAY_RANK,
953         INLINE_TYPE_ELEMENT_TYPE
954 } InlineMethod;
955
956 typedef struct
957 {
958         MonoClassField *field;
959 } MonoRuntimeFieldInfo;
960
961 typedef struct
962 {
963         guint32 locals_size;
964         guint32 args_size;
965         MonoRuntimeFieldInfo *field_info;
966         guint32 offsets[1];
967 } MethodRuntimeData;
968
969 static void
970 write32(unsigned char *p, guint32 v)
971 {
972         p[0] = v & 0xff;
973         p[1] = (v >> 8) & 0xff;
974         p[2] = (v >> 16) & 0xff;
975         p[3] = (v >> 24) & 0xff;
976 }
977
978 static CRITICAL_SECTION calc_section;
979
980 static void
981 calc_offsets (MonoImage *image, MonoMethod *method)
982 {
983         int i, align, size, offset = 0;
984         MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
985         MonoMethodSignature *signature = method->signature;
986         register const unsigned char *ip, *end;
987         const MonoOpcode *opcode;
988         guint32 token;
989         MonoMethod *m;
990         MonoClass *class;
991         MonoDomain *domain = mono_domain_get ();
992         MethodRuntimeData *rtd;
993         int n_fields = 0;
994
995         mono_profiler_method_jit (method); /* sort of... */
996         /* intern the strings in the method. */
997         ip = header->code;
998         end = ip + header->code_size;
999         while (ip < end) {
1000                 i = *ip;
1001                 if (*ip == 0xfe) {
1002                         ip++;
1003                         i = *ip + 256;
1004                 }
1005                 opcode = &mono_opcodes [i];
1006                 switch (opcode->argument) {
1007                 case MonoInlineNone:
1008                         ++ip;
1009                         break;
1010                 case MonoInlineString:
1011                         mono_ldstr (domain, image, mono_metadata_token_index (read32 (ip + 1)));
1012                         ip += 5;
1013                         break;
1014                 case MonoInlineType:
1015                         if (method->wrapper_type == MONO_WRAPPER_NONE) {
1016                                 class = mono_class_get (image, read32 (ip + 1));
1017                                 mono_class_init (class);
1018                                 if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE))
1019                                         mono_class_vtable (domain, class);
1020                         }
1021                         ip += 5;
1022                         break;
1023                 case MonoInlineField:
1024                         n_fields++;
1025                         ip += 5;
1026                         break;
1027                 case MonoInlineMethod:
1028                         if (method->wrapper_type == MONO_WRAPPER_NONE) {
1029                                 m = mono_get_method (image, read32 (ip + 1), NULL);
1030                                 mono_class_init (m->klass);
1031                                 if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
1032                                         mono_class_vtable (domain, m->klass);
1033                         }
1034                         ip += 5;
1035                         break;
1036                 case MonoInlineTok:
1037                 case MonoInlineSig:
1038                 case MonoShortInlineR:
1039                 case MonoInlineI:
1040                 case MonoInlineBrTarget:
1041                         ip += 5;
1042                         break;
1043                 case MonoInlineVar:
1044                         ip += 3;
1045                         break;
1046                 case MonoShortInlineVar:
1047                 case MonoShortInlineI:
1048                 case MonoShortInlineBrTarget:
1049                         ip += 2;
1050                         break;
1051                 case MonoInlineSwitch: {
1052                         guint32 n;
1053                         ++ip;
1054                         n = read32 (ip);
1055                         ip += 4;
1056                         ip += 4 * n;
1057                         break;
1058                 }
1059                 case MonoInlineR:
1060                 case MonoInlineI8:
1061                         ip += 9;
1062                         break;
1063                 default:
1064                         g_assert_not_reached ();
1065                 }
1066
1067         }
1068
1069         /* the rest needs to be locked so it is only done once */
1070         EnterCriticalSection(&calc_section);
1071         if (method->info != NULL) {
1072                 LeaveCriticalSection(&calc_section);
1073                 mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
1074                 return;
1075         }
1076         rtd = (MethodRuntimeData *)g_malloc0 (sizeof(MethodRuntimeData) + (header->num_locals - 1 + signature->hasthis + signature->param_count) * sizeof(guint32));
1077         for (i = 0; i < header->num_locals; ++i) {
1078                 size = mono_type_size (header->locals [i], &align);
1079                 offset += align - 1;
1080                 offset &= ~(align - 1);
1081                 rtd->offsets [i] = offset;
1082                 offset += size;
1083         }
1084         rtd->locals_size = offset;
1085         offset = 0;
1086         if (signature->hasthis) {
1087                 offset += sizeof (gpointer) - 1;
1088                 offset &= ~(sizeof (gpointer) - 1);
1089                 rtd->offsets [header->num_locals] = offset;
1090                 offset += sizeof (gpointer);
1091         }
1092         for (i = 0; i < signature->param_count; ++i) {
1093                 if (signature->pinvoke) {
1094                         size = mono_type_native_stack_size (signature->params [i], &align);
1095                         align = 8;
1096                 }
1097                 else
1098                         size = mono_type_stack_size (signature->params [i], &align);
1099                 offset += align - 1;
1100                 offset &= ~(align - 1);
1101                 rtd->offsets [signature->hasthis + header->num_locals + i] = offset;
1102                 offset += size;
1103         }
1104         rtd->args_size = offset;
1105         rtd->field_info = g_malloc(n_fields * sizeof(MonoRuntimeFieldInfo));
1106
1107         header->code = g_memdup(header->code, header->code_size);
1108         n_fields = 0;
1109         ip = header->code;
1110         end = ip + header->code_size;
1111         while (ip < end) {
1112                 i = *ip;
1113                 if (*ip == 0xfe) {
1114                         ip++;
1115                         i = *ip + 256;
1116                 }
1117                 opcode = &mono_opcodes [i];
1118                 switch (opcode->argument) {
1119                 case MonoInlineNone:
1120                         ++ip;
1121                         break;
1122                 case MonoInlineString:
1123                         ip += 5;
1124                         break;
1125                 case MonoInlineType:
1126                         ip += 5;
1127                         break;
1128                 case MonoInlineField:
1129                         token = read32 (ip + 1);
1130                         rtd->field_info[n_fields].field = mono_field_from_token (image, token, &class);
1131                         mono_class_vtable (domain, class);
1132                         g_assert(rtd->field_info[n_fields].field->parent == class);
1133                         write32 ((unsigned char *)ip + 1, n_fields);
1134                         n_fields++;
1135                         ip += 5;
1136                         break;
1137                 case MonoInlineMethod:
1138                         ip += 5;
1139                         break;
1140                 case MonoInlineTok:
1141                 case MonoInlineSig:
1142                 case MonoShortInlineR:
1143                 case MonoInlineI:
1144                 case MonoInlineBrTarget:
1145                         ip += 5;
1146                         break;
1147                 case MonoInlineVar:
1148                         ip += 3;
1149                         break;
1150                 case MonoShortInlineVar:
1151                 case MonoShortInlineI:
1152                 case MonoShortInlineBrTarget:
1153                         ip += 2;
1154                         break;
1155                 case MonoInlineSwitch: {
1156                         guint32 n;
1157                         ++ip;
1158                         n = read32 (ip);
1159                         ip += 4;
1160                         ip += 4 * n;
1161                         break;
1162                 }
1163                 case MonoInlineR:
1164                 case MonoInlineI8:
1165                         ip += 9;
1166                         break;
1167                 default:
1168                         g_assert_not_reached ();
1169                 }
1170
1171         }
1172
1173         /*
1174          * We store the inline info in addr, since it's unused for IL methods.
1175          */
1176         if (method->klass == mono_defaults.string_class) {
1177                 if (strcmp (method->name, "get_Length") == 0)
1178                         method->addr = GUINT_TO_POINTER (INLINE_STRING_LENGTH);
1179                 else if (strcmp (method->name, "get_Chars") == 0)
1180                         method->addr = GUINT_TO_POINTER (INLINE_STRING_GET_CHARS);
1181         } else if (method->klass == mono_defaults.array_class) {
1182                 if (strcmp (method->name, "get_Length") == 0)
1183                         method->addr = GUINT_TO_POINTER (INLINE_ARRAY_LENGTH);
1184                 else if (strcmp (method->name, "get_Rank") == 0 || strcmp (method->name, "GetRank") == 0)
1185                         method->addr = GUINT_TO_POINTER (INLINE_ARRAY_RANK);
1186         } else if (method->klass == mono_defaults.monotype_class) {
1187                 if (strcmp (method->name, "GetElementType") == 0)
1188                         method->addr = GUINT_TO_POINTER (INLINE_TYPE_ELEMENT_TYPE);
1189         }
1190         mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
1191         method->info = rtd;
1192         LeaveCriticalSection(&calc_section);
1193 }
1194
1195 #define LOCAL_POS(n)            (frame->locals + rtd->offsets [n])
1196 #define LOCAL_TYPE(header, n)   ((header)->locals [(n)])
1197
1198 #define ARG_POS(n)              (args_pointers [(n)])
1199 #define ARG_TYPE(sig, n)        ((n) ? (sig)->params [(n) - (sig)->hasthis] : \
1200                                 (sig)->hasthis ? &frame->method->klass->this_arg: (sig)->params [(0)])
1201
1202 typedef struct _vtallocation vtallocation;
1203
1204 struct _vtallocation {
1205         vtallocation *next;
1206         guint32 size;
1207         guint32 max_size;
1208         union {
1209                 char data [MONO_ZERO_LEN_ARRAY];
1210                 double force_alignment;
1211         } u;
1212 };
1213
1214 #define vt_allocmem(sz, var) \
1215         do { \
1216                 vtallocation *tmp, *prev; \
1217                 prev = NULL; \
1218                 tmp = vtalloc; \
1219                 while (tmp && (tmp->max_size < (sz))) { \
1220                         prev = tmp; \
1221                         tmp = tmp->next; \
1222                 } \
1223                 if (!tmp) { \
1224                         tmp = alloca (sizeof (vtallocation) + (sz));    \
1225                         tmp->max_size = (sz);   \
1226                         g_assert ((sz) < 10000);        \
1227                 } \
1228                 else \
1229                         if (prev) \
1230                                 prev->next = tmp->next; \
1231                         else \
1232                                 vtalloc = tmp->next; \
1233                 tmp->size = (sz);       \
1234                 var = tmp->u.data;      \
1235         } while(0)
1236
1237 #define vt_alloc(vtype,sp,native)       \
1238         if ((vtype)->type == MONO_TYPE_VALUETYPE && !(vtype)->data.klass->enumtype) {   \
1239                 if (!(vtype)->byref) {  \
1240                         guint32 vtsize; \
1241                         if (native) vtsize = mono_class_native_size ((vtype)->data.klass, NULL);        \
1242                         else vtsize = mono_class_value_size ((vtype)->data.klass, NULL);        \
1243                         vt_allocmem(vtsize, (sp)->data.vt);     \
1244                 }       \
1245         }
1246
1247 #define vt_free(sp)     \
1248         do {    \
1249                 if ((sp)->type == VAL_VALUET) { \
1250                         vtallocation *tmp = (vtallocation*)(((char*)(sp)->data.vt) - G_STRUCT_OFFSET (vtallocation, u));        \
1251                         tmp->next = vtalloc; \
1252                         vtalloc = tmp; \
1253                 }       \
1254         } while (0)
1255
1256 #define stackvalpush(val, sp) \
1257         do {    \
1258                 (sp)->type = (val)->type; \
1259                 (sp)->data = (val)->data; \
1260                 if ((val)->type == VAL_VALUET) {        \
1261                         vtallocation *vala = (vtallocation*)(((char*)(val)->data.vt) - G_STRUCT_OFFSET (vtallocation, u));      \
1262                         vt_allocmem(vala->size, (sp)->data.vt); \
1263                         memcpy((sp)->data.vt, (val)->data.vt, vala->size);      \
1264                 }       \
1265                 (sp)++; \
1266         } while (0)
1267
1268 #define stackvalcpy(src, dest) \
1269         do {    \
1270                 (dest)->type = (src)->type; \
1271                 (dest)->data = (src)->data; \
1272                 if ((dest)->type == VAL_VALUET) {       \
1273                         vtallocation *tmp = (vtallocation*)(((char*)(src)->data.vt) - G_STRUCT_OFFSET (vtallocation, u));       \
1274                         memcpy((dest)->data.vt, (src)->data.vt, tmp->size);     \
1275                 }       \
1276         } while (0)
1277
1278 /*
1279 static void
1280 verify_method (MonoMethod *m)
1281 {
1282         GSList *errors, *tmp;
1283         MonoVerifyInfo *info;
1284
1285         errors = mono_method_verify (m, MONO_VERIFY_ALL);
1286         if (errors)
1287                 g_print ("Method %s.%s::%s has invalid IL.\n", m->klass->name_space, m->klass->name, m->name);
1288         for (tmp = errors; tmp; tmp = tmp->next) {
1289                 info = tmp->data;
1290                 g_print ("%s\n", info->message);
1291         }
1292         if (errors)
1293                 G_BREAKPOINT ();
1294         mono_free_verify_list (errors);
1295 }
1296 */
1297
1298 #define MYGUINT64_MAX 18446744073709551615ULL
1299 #define MYGINT64_MAX 9223372036854775807LL
1300 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
1301
1302 #define MYGUINT32_MAX 4294967295U
1303 #define MYGINT32_MAX 2147483647
1304 #define MYGINT32_MIN (-MYGINT32_MAX -1)
1305         
1306 #define CHECK_ADD_OVERFLOW(a,b) \
1307         (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0  \
1308         : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
1309
1310 #define CHECK_SUB_OVERFLOW(a,b) \
1311         (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0   \
1312         : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
1313
1314 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1315         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1316
1317 #define CHECK_SUB_OVERFLOW_UN(a,b) \
1318         (guint32)(a) < (guint32)(b) ? -1 : 0
1319
1320 #define CHECK_ADD_OVERFLOW64(a,b) \
1321         (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0  \
1322         : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
1323
1324 #define CHECK_SUB_OVERFLOW64(a,b) \
1325         (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0   \
1326         : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
1327
1328 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
1329         (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
1330
1331 #define CHECK_SUB_OVERFLOW64_UN(a,b) \
1332         (guint64)(a) < (guint64)(b) ? -1 : 0
1333
1334 #if SIZEOF_VOID_P == 4
1335 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
1336 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
1337 #else
1338 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
1339 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
1340 #endif
1341
1342 /* Resolves to TRUE if the operands would overflow */
1343 #define CHECK_MUL_OVERFLOW(a,b) \
1344         ((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
1345         (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
1346         (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
1347         (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
1348         (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
1349         (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
1350         (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
1351
1352 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1353         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1354         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1355
1356 #define CHECK_MUL_OVERFLOW64(a,b) \
1357         ((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
1358         (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
1359         (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
1360         (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
1361         (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
1362         (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
1363         (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
1364
1365 #define CHECK_MUL_OVERFLOW64_UN(a,b) \
1366         ((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
1367         (guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
1368
1369 #if SIZEOF_VOID_P == 4
1370 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
1371 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
1372 #else
1373 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
1374 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
1375 #endif
1376
1377 static MonoObject*
1378 interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1379 {
1380         MonoInvocation frame;
1381         ThreadContext *context = TlsGetValue (thread_context_id);
1382         MonoObject *retval = NULL;
1383         MonoMethodSignature *sig = method->signature;
1384         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1385         int i, type, isobject = 0;
1386         void *ret;
1387         stackval result;
1388         stackval *args = alloca (sizeof (stackval) * sig->param_count);
1389         ThreadContext context_struct;
1390         MonoInvocation *old_frame;
1391
1392         if (context == NULL) {
1393                 context = &context_struct;
1394                 context_struct.base_frame = &frame;
1395                 context_struct.current_frame = NULL;
1396                 context_struct.env_frame = NULL;
1397                 context_struct.current_env = NULL;
1398                 context_struct.search_for_handler = 0;
1399                 TlsSetValue (thread_context_id, context);
1400         }
1401         else
1402                 old_frame = context->current_frame;
1403
1404
1405         /* FIXME: Set frame for execption handling.  */
1406
1407         switch (sig->ret->type) {
1408         case MONO_TYPE_VOID:
1409                 break;
1410         case MONO_TYPE_STRING:
1411         case MONO_TYPE_OBJECT:
1412         case MONO_TYPE_CLASS:
1413         case MONO_TYPE_ARRAY:
1414         case MONO_TYPE_SZARRAY:
1415                 isobject = 1;
1416                 break;
1417         case MONO_TYPE_VALUETYPE:
1418                 retval = mono_object_new (mono_domain_get (), klass);
1419                 ret = ((char*)retval) + sizeof (MonoObject);
1420                 if (!sig->ret->data.klass->enumtype)
1421                         result.data.vt = ret;
1422                 break;
1423         default:
1424                 retval = mono_object_new (mono_domain_get (), klass);
1425                 ret = ((char*)retval) + sizeof (MonoObject);
1426                 break;
1427         }
1428
1429         for (i = 0; i < sig->param_count; ++i) {
1430                 if (sig->params [i]->byref) {
1431                         args [i].type = VAL_POINTER;
1432                         args [i].data.p = params [i];
1433                         continue;
1434                 }
1435                 type = sig->params [i]->type;
1436 handle_enum:
1437                 switch (type) {
1438                 case MONO_TYPE_U1:
1439                 case MONO_TYPE_I1:
1440                 case MONO_TYPE_BOOLEAN:
1441                         args [i].type = VAL_I32;
1442                         args [i].data.i = *(MonoBoolean*)params [i];
1443                         break;
1444                 case MONO_TYPE_U2:
1445                 case MONO_TYPE_I2:
1446                 case MONO_TYPE_CHAR:
1447                         args [i].type = VAL_I32;
1448                         args [i].data.i = *(gint16*)params [i];
1449                         break;
1450 #if SIZEOF_VOID_P == 4
1451                 case MONO_TYPE_U: /* use VAL_POINTER? */
1452                 case MONO_TYPE_I:
1453 #endif
1454                 case MONO_TYPE_U4:
1455                 case MONO_TYPE_I4:
1456                         args [i].type = VAL_I32;
1457                         args [i].data.i = *(gint32*)params [i];
1458                         break;
1459 #if SIZEOF_VOID_P == 8
1460                 case MONO_TYPE_U:
1461                 case MONO_TYPE_I:
1462 #endif
1463                 case MONO_TYPE_U8:
1464                 case MONO_TYPE_I8:
1465                         args [i].type = VAL_I64;
1466                         args [i].data.l = *(gint64*)params [i];
1467                         break;
1468                 case MONO_TYPE_VALUETYPE:
1469                         if (sig->params [i]->data.klass->enumtype) {
1470                                 type = sig->params [i]->data.klass->enum_basetype->type;
1471                                 goto handle_enum;
1472                         } else {
1473                                 args [i].type = VAL_POINTER;
1474                                 args [i].data.p = params [i];
1475                         }
1476                         break;
1477                 case MONO_TYPE_STRING:
1478                 case MONO_TYPE_CLASS:
1479                 case MONO_TYPE_ARRAY:
1480                 case MONO_TYPE_SZARRAY:
1481                 case MONO_TYPE_OBJECT:
1482                         args [i].type = VAL_OBJ;
1483                         args [i].data.p = params [i];
1484                         break;
1485                 default:
1486                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1487                 }
1488         }
1489
1490         if (method->klass->valuetype)
1491                 /* Unbox the instance, since valuetype methods expect an interior pointer. */
1492                 obj = mono_object_unbox (obj);
1493
1494         INIT_FRAME(&frame,context->current_frame,obj,args,&result,method);
1495         if (exc)
1496                 frame.invoke_trap = 1;
1497         ves_exec_method_with_context (&frame, context);
1498         if (context == &context_struct)
1499                 TlsSetValue (thread_context_id, NULL);
1500         else
1501                 context->current_frame = old_frame;
1502         if (frame.ex != NULL) {
1503                 if (exc != NULL) {
1504                         *exc = (MonoObject*) frame.ex;
1505                         if (*exc == (MonoObject *)quit_exception)
1506                                 mono_print_unhandled_exception(*exc);
1507                         return NULL;
1508                 }
1509                 if (context->current_env != NULL) {
1510                         context->env_frame->ex = frame.ex;
1511                         longjmp(*context->current_env, 1);
1512                 }
1513                 else
1514                         printf("dropped exception...\n");
1515         }
1516         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1517                 return NULL;
1518         if (isobject || method->string_ctor)
1519                 return result.data.p;
1520         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1521         return retval;
1522 }
1523
1524 static MonoMethod *
1525 get_native_wrapper(MonoMethod *method, ThreadContext *context)
1526 {
1527         jmp_buf env;
1528         jmp_buf *old_env;
1529         MonoMethod *wrapper;
1530         old_env = context->current_env;
1531         if (setjmp(env) != 0) {
1532                 context->current_env = old_env;
1533                 context->search_for_handler = 1;
1534                 return NULL;
1535         }
1536         context->current_env = &env;
1537         wrapper = mono_marshal_get_native_wrapper (method);
1538         context->current_env = old_env;
1539         return wrapper;
1540 }
1541
1542 /*
1543  * Need to optimize ALU ops when natural int == int32 
1544  *
1545  * IDEA: if we maintain a stack of ip, sp to be checked
1546  * in the return opcode, we could inline simple methods that don't
1547  * use the stack or local variables....
1548  * 
1549  * The {,.S} versions of many opcodes can/should be merged to reduce code
1550  * duplication.
1551  * 
1552  */
1553 static void 
1554 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
1555 {
1556         MonoDomain *domain = mono_domain_get ();        
1557         MonoInvocation child_frame;
1558         MonoMethodHeader *header;
1559         MonoMethodSignature *signature;
1560         MonoImage *image;
1561         GSList *finally_ips = NULL;
1562         const unsigned char *endfinally_ip = NULL;
1563         register const unsigned char *ip;
1564         register stackval *sp = NULL;
1565         MethodRuntimeData *rtd;
1566         void **args_pointers;
1567         gint tracing = global_tracing;
1568         unsigned char tail_recursion = 0;
1569         unsigned char unaligned_address = 0;
1570         unsigned char volatile_address = 0;
1571         vtallocation *vtalloc = NULL;
1572         MonoVTable *method_class_vt;
1573         GOTO_LABEL_VARS;
1574
1575         frame->ex = NULL;
1576         frame->ip = ip = NULL;
1577         context->current_frame = frame;
1578
1579         if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1580                 frame->method = get_native_wrapper (frame->method, context);
1581                 if (frame->method == NULL)
1582                         goto exit_frame;
1583         }
1584
1585         method_class_vt = mono_class_vtable (domain, frame->method->klass);
1586         if (!method_class_vt->initialized)
1587                 mono_runtime_class_init (method_class_vt);
1588         signature = frame->method->signature;
1589
1590         DEBUG_ENTER ();
1591
1592         header = ((MonoMethodNormal *)frame->method)->header;
1593
1594         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
1595                 if (!frame->method->addr) {
1596                         /* ugly, but needed by the iflags setting in loader.c */
1597                         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
1598                                 ves_runtime_method (frame, context);
1599                                 if (frame->ex)
1600                                         goto handle_exception;
1601                                 goto exit_frame;
1602                         }
1603                         if (frame->method->addr) {
1604                                 frame->ex = (MonoException*)mono_get_exception_missing_method ();
1605                                 goto handle_exception;
1606                         }
1607                 }
1608                 ves_pinvoke_method (frame, frame->method->signature, frame->method->addr, 
1609                             frame->method->string_ctor, context);
1610                 if (frame->ex)
1611                         goto handle_exception;
1612                 goto exit_frame;
1613         } 
1614
1615         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
1616                 ves_runtime_method (frame, context);
1617                 if (frame->ex)
1618                         goto handle_exception;
1619                 goto exit_frame;
1620         } 
1621
1622         /*verify_method (frame->method);*/
1623
1624         image = frame->method->klass->image;
1625
1626         if (!frame->method->info)
1627                 calc_offsets (image, frame->method);
1628         rtd = frame->method->info;
1629
1630         /*
1631          * with alloca we get the expected huge performance gain
1632          * stackval *stack = g_new0(stackval, header->max_stack);
1633          */
1634         g_assert (header->max_stack < 10000);
1635         sp = frame->stack = alloca (sizeof (stackval) * header->max_stack);
1636
1637         if (header->num_locals) {
1638                 g_assert (rtd->locals_size < 65536);
1639                 frame->locals = alloca (rtd->locals_size);
1640                 /* 
1641                  * yes, we do it unconditionally, because it needs to be done for
1642                  * some cases anyway and checking for that would be even slower.
1643                  */
1644                 memset (frame->locals, 0, rtd->locals_size);
1645         }
1646
1647         /*
1648          * Copy args from stack_args to args.
1649          */
1650         if (signature->param_count || signature->hasthis) {
1651                 int i;
1652                 int has_this = signature->hasthis;
1653
1654                 g_assert (rtd->args_size < 10000);
1655                 frame->args = alloca (rtd->args_size);
1656                 g_assert ((signature->param_count + has_this) < 1000);
1657                 args_pointers = alloca (sizeof(void*) * (signature->param_count + has_this));
1658                 if (has_this) {
1659                         gpointer *this_arg;
1660                         this_arg = args_pointers [0] = frame->args;
1661                         *this_arg = frame->obj;
1662                 }
1663                 for (i = 0; i < signature->param_count; ++i) {
1664                         args_pointers [i + has_this] = frame->args + rtd->offsets [header->num_locals + has_this + i];
1665                         stackval_to_data (signature->params [i], frame->stack_args + i, args_pointers [i + has_this], signature->pinvoke);
1666                 }
1667         }
1668
1669         child_frame.parent = frame;
1670         frame->child = &child_frame;
1671         frame->ex = NULL;
1672
1673         /* ready to go */
1674         ip = header->code;
1675
1676         /*
1677          * using while (ip < end) may result in a 15% performance drop, 
1678          * but it may be useful for debug
1679          */
1680         while (1) {
1681         main_loop:
1682                 /*g_assert (sp >= stack);*/
1683 #if DEBUG_INTERP
1684                 opcode_count++;
1685                 if (tracing > 1) {
1686                         char *ins, *discode;
1687                         if (sp > frame->stack) {
1688                                 ins = dump_stack (frame->stack, sp);
1689                         } else {
1690                                 ins = g_strdup ("");
1691                         }
1692                         output_indent ();
1693                         discode = mono_disasm_code_one (NULL, frame->method, ip, NULL);
1694                         discode [strlen (discode) - 1] = 0; /* no \n */
1695                         g_print ("(%u) %-29s %s\n", GetCurrentThreadId(), discode, ins);
1696                         g_free (ins);
1697                         g_free (discode);
1698                 }
1699 #endif
1700                 
1701                 SWITCH (*ip) {
1702                 CASE (CEE_NOP) 
1703                         ++ip;
1704                         BREAK;
1705                 CASE (CEE_BREAK)
1706                         ++ip;
1707                         G_BREAKPOINT (); /* this is not portable... */
1708                         BREAK;
1709                 CASE (CEE_LDARG_0)
1710                 CASE (CEE_LDARG_1)
1711                 CASE (CEE_LDARG_2)
1712                 CASE (CEE_LDARG_3) {
1713                         int n = (*ip)-CEE_LDARG_0;
1714                         ++ip;
1715                         vt_alloc (ARG_TYPE (signature, n), sp, signature->pinvoke);
1716                         stackval_from_data (ARG_TYPE (signature, n), sp, ARG_POS (n), signature->pinvoke);
1717                         ++sp;
1718                         BREAK;
1719                 }
1720                 CASE (CEE_LDLOC_0)
1721                 CASE (CEE_LDLOC_1)
1722                 CASE (CEE_LDLOC_2)
1723                 CASE (CEE_LDLOC_3) {
1724                         int n = (*ip)-CEE_LDLOC_0;
1725                         MonoType *vartype = LOCAL_TYPE (header, n);
1726                         ++ip;
1727                         if (vartype->type == MONO_TYPE_I4) {
1728                                 sp->type = VAL_I32;
1729                                 sp->data.i = *(gint32*) LOCAL_POS (n);
1730                                 ++sp;
1731                                 BREAK;
1732                         } else {
1733                                 vt_alloc (vartype, sp, FALSE);
1734                                 stackval_from_data (vartype, sp, LOCAL_POS (n), FALSE);
1735                         }
1736                         ++sp;
1737                         BREAK;
1738                 }
1739                 CASE (CEE_STLOC_0)
1740                 CASE (CEE_STLOC_1)
1741                 CASE (CEE_STLOC_2)
1742                 CASE (CEE_STLOC_3) {
1743                         int n = (*ip)-CEE_STLOC_0;
1744                         ++ip;
1745                         --sp;
1746                         if ((LOCAL_TYPE (header, n))->type == MONO_TYPE_I4) {
1747                                 gint32 *p = (gint32*)LOCAL_POS (n);
1748                                 *p = sp->data.i;
1749                                 BREAK;
1750                         } else {
1751                                 stackval_to_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n), FALSE);
1752                                 vt_free (sp);
1753                                 BREAK;
1754                         }
1755                 }
1756                 CASE (CEE_LDARG_S)
1757                         ++ip;
1758                         vt_alloc (ARG_TYPE (signature, *ip), sp, signature->pinvoke);
1759                         stackval_from_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip), signature->pinvoke);
1760                         ++sp;
1761                         ++ip;
1762                         BREAK;
1763                 CASE (CEE_LDARGA_S) {
1764                         ++ip;
1765                         sp->data.vt = ARG_POS (*ip);
1766                         sp->type = VAL_MP;
1767                         ++sp;
1768                         ++ip;
1769                         BREAK;
1770                 }
1771                 CASE (CEE_STARG_S)
1772                         ++ip;
1773                         --sp;
1774                         stackval_to_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip), signature->pinvoke);
1775                         vt_free (sp);
1776                         ++ip;
1777                         BREAK;
1778                 CASE (CEE_LDLOC_S)
1779                         ++ip;
1780                         vt_alloc (LOCAL_TYPE (header, *ip), sp, FALSE);
1781                         stackval_from_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip), FALSE);
1782                         ++ip;
1783                         ++sp;
1784                         BREAK;
1785                 CASE (CEE_LDLOCA_S) {
1786                         ++ip;
1787                         sp->data.p = LOCAL_POS (*ip);
1788                         sp->type = VAL_MP;
1789                         ++sp;
1790                         ++ip;
1791                         BREAK;
1792                 }
1793                 CASE (CEE_STLOC_S)
1794                         ++ip;
1795                         --sp;
1796                         stackval_to_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip), FALSE);
1797                         vt_free (sp);
1798                         ++ip;
1799                         BREAK;
1800                 CASE (CEE_LDNULL) 
1801                         ++ip;
1802                         sp->type = VAL_OBJ;
1803                         sp->data.p = NULL;
1804                         ++sp;
1805                         BREAK;
1806                 CASE (CEE_LDC_I4_M1)
1807                         ++ip;
1808                         sp->type = VAL_I32;
1809                         sp->data.i = -1;
1810                         ++sp;
1811                         BREAK;
1812                 CASE (CEE_LDC_I4_0)
1813                 CASE (CEE_LDC_I4_1)
1814                 CASE (CEE_LDC_I4_2)
1815                 CASE (CEE_LDC_I4_3)
1816                 CASE (CEE_LDC_I4_4)
1817                 CASE (CEE_LDC_I4_5)
1818                 CASE (CEE_LDC_I4_6)
1819                 CASE (CEE_LDC_I4_7)
1820                 CASE (CEE_LDC_I4_8)
1821                         sp->type = VAL_I32;
1822                         sp->data.i = (*ip) - CEE_LDC_I4_0;
1823                         ++sp;
1824                         ++ip;
1825                         BREAK;
1826                 CASE (CEE_LDC_I4_S) 
1827                         ++ip;
1828                         sp->type = VAL_I32;
1829                         sp->data.i = *(const gint8 *)ip;
1830                         ++ip;
1831                         ++sp;
1832                         BREAK;
1833                 CASE (CEE_LDC_I4)
1834                         ++ip;
1835                         sp->type = VAL_I32;
1836                         sp->data.i = read32 (ip);
1837                         ip += 4;
1838                         ++sp;
1839                         BREAK;
1840                 CASE (CEE_LDC_I8)
1841                         ++ip;
1842                         sp->type = VAL_I64;
1843                         sp->data.l = read64 (ip);
1844                         ip += 8;
1845                         ++sp;
1846                         BREAK;
1847                 CASE (CEE_LDC_R4) {
1848                         float val;
1849                         ++ip;
1850                         sp->type = VAL_DOUBLE;
1851                         readr4 (ip, &val);
1852                         sp->data.f = val;
1853                         ip += 4;
1854                         ++sp;
1855                         BREAK;
1856                 }
1857                 CASE (CEE_LDC_R8) 
1858                         ++ip;
1859                         sp->type = VAL_DOUBLE;
1860                         readr8(ip, &sp->data.f);
1861                         ip += 8;
1862                         ++sp;
1863                         BREAK;
1864                 CASE (CEE_UNUSED99) ves_abort (); BREAK;
1865                 CASE (CEE_DUP) 
1866                         stackvalpush(sp - 1, sp);
1867                         ++ip; 
1868                         BREAK;
1869                 CASE (CEE_POP)
1870                         ++ip;
1871                         --sp;
1872                         vt_free (sp);
1873                         BREAK;
1874                 CASE (CEE_JMP) ves_abort(); BREAK;
1875                 CASE (CEE_CALLVIRT) /* Fall through */
1876                 CASE (CEE_CALLI)    /* Fall through */
1877                 CASE (CEE_CALL) {
1878                         MonoMethodSignature *csignature;
1879                         stackval retval;
1880                         stackval *endsp = sp;
1881                         guint32 token;
1882                         int virtual = *ip == CEE_CALLVIRT;
1883                         int calli = *ip == CEE_CALLI;
1884                         unsigned char *code = NULL;
1885
1886                         /*
1887                          * We ignore tail recursion for now.
1888                          */
1889                         tail_recursion = 0;
1890
1891                         frame->ip = ip;
1892                         
1893                         ++ip;
1894                         token = read32 (ip);
1895                         ip += 4;
1896                         if (calli) {
1897                                 MonoJitInfo *ji;
1898                                 --sp;
1899                                 code = sp->data.p;
1900                                 if (frame->method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE &&
1901                                         (ji = mono_jit_info_table_find (mono_root_domain, code)) != NULL) {
1902                                         child_frame.method = ji->method;
1903                                         csignature = ji->method->signature;
1904                                 }
1905                                 else if (frame->method->wrapper_type != MONO_WRAPPER_NONE) {
1906                                         csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (frame->method, token);
1907                                         child_frame.method = NULL;
1908                                 } else {
1909                                         g_assert_not_reached ();
1910                                 }
1911                                 g_assert (code);
1912                         } else {
1913                                 if (frame->method->wrapper_type != MONO_WRAPPER_NONE) 
1914                                         child_frame.method = (MonoMethod *)mono_method_get_wrapper_data (frame->method, token);
1915                                 else
1916                                         child_frame.method = mono_get_method (image, token, NULL);
1917                                 if (!child_frame.method)
1918                                         THROW_EX (mono_get_exception_missing_method (), ip -5);
1919                                 csignature = child_frame.method->signature;
1920                                 if (virtual) {
1921                                         stackval *this_arg = &sp [-csignature->param_count-1];
1922                                         if (!this_arg->data.p)
1923                                                 THROW_EX (mono_get_exception_null_reference(), ip - 5);
1924                                         child_frame.method = get_virtual_method (domain, child_frame.method, this_arg);
1925                                         if (!child_frame.method)
1926                                                 THROW_EX (mono_get_exception_missing_method (), ip -5);
1927                                 }
1928                         }
1929
1930                         if (frame->method->wrapper_type == MONO_WRAPPER_NONE)
1931                                 if (child_frame.method && child_frame.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1932                                         child_frame.method = mono_marshal_get_synchronized_wrapper (child_frame.method);
1933
1934                         g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C);
1935                         /* decrement by the actual number of args */
1936                         if (csignature->param_count) {
1937                                 sp -= csignature->param_count;
1938                                 child_frame.stack_args = sp;
1939                         } else {
1940                                 child_frame.stack_args = NULL;
1941                         }
1942                         if (csignature->hasthis) {
1943                                 g_assert (sp >= frame->stack);
1944                                 --sp;
1945                                 /*
1946                                  * It may also be a TP from LD(S)FLDA
1947                                  * g_assert (sp->type == VAL_OBJ || sp->type == VAL_MP);
1948                                  */
1949                                 if (sp->type == VAL_OBJ && child_frame.method &&
1950                                     child_frame.method->klass->valuetype) /* unbox it */
1951                                         child_frame.obj = (char*)sp->data.p + sizeof (MonoObject);
1952                                 else
1953                                         child_frame.obj = sp->data.p;
1954                         } else {
1955                                 child_frame.obj = NULL;
1956                         }
1957                         if (csignature->ret->type != MONO_TYPE_VOID) {
1958                                 vt_alloc (csignature->ret, &retval, csignature->pinvoke);
1959                                 child_frame.retval = &retval;
1960                         } else {
1961                                 child_frame.retval = NULL;
1962                         }
1963
1964                         child_frame.ip = NULL;
1965                         child_frame.ex = NULL;
1966                         child_frame.ex_handler = NULL;
1967
1968                         if (!child_frame.method) {
1969                                 g_assert (code);
1970                                 ves_pinvoke_method (&child_frame, csignature, (MonoFunc) code, FALSE, context);
1971                                 if (child_frame.ex) {
1972                                         frame->ex = child_frame.ex;
1973                                         goto handle_exception;
1974                                 }
1975                         } else if (csignature->hasthis && sp->type == VAL_OBJ &&
1976                                         ((MonoObject *)sp->data.p)->vtable->klass == mono_defaults.transparent_proxy_class) {
1977                                 g_assert (child_frame.method);
1978                                 child_frame.method = mono_marshal_get_remoting_invoke (child_frame.method);
1979                                 ves_exec_method_with_context (&child_frame, context);
1980                         } else {
1981                                 switch (GPOINTER_TO_UINT (child_frame.method->addr)) {
1982                                 case INLINE_STRING_LENGTH:
1983                                         retval.type = VAL_I32;
1984                                         retval.data.i = ((MonoString*)sp->data.p)->length;
1985                                         /*g_print ("length of '%s' is %d\n", mono_string_to_utf8 (sp->data.p), retval.data.i);*/
1986                                         break;
1987                                 case INLINE_STRING_GET_CHARS: {
1988                                         int idx = GET_NATI(sp [1]);
1989                                         if ((idx < 0) || (idx >= mono_string_length ((MonoString*)sp->data.p))) {
1990                                                 child_frame.ex = mono_get_exception_index_out_of_range ();
1991                                                 FILL_IN_TRACE(child_frame.ex, &child_frame);
1992                                         }
1993                                         else {
1994                                                 retval.type = VAL_I32;
1995                                                 retval.data.i = mono_string_chars((MonoString*)sp->data.p)[idx];
1996                                         }
1997                                         break;
1998                                 }
1999                                 case INLINE_ARRAY_LENGTH:
2000                                         retval.type = VAL_I32;
2001                                         retval.data.i = mono_array_length ((MonoArray*)sp->data.p);
2002                                         break;
2003                                 case INLINE_ARRAY_RANK:
2004                                         retval.type = VAL_I32;
2005                                         retval.data.i = mono_object_class (sp->data.p)->rank;
2006                                         break;
2007                                 case INLINE_TYPE_ELEMENT_TYPE:
2008                                         retval.type = VAL_OBJ;
2009                                         {
2010                                                 MonoClass *c = mono_class_from_mono_type (((MonoReflectionType*)sp->data.p)->type);
2011                                                 if (c->enumtype && c->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
2012                                                         retval.data.p = mono_type_get_object (domain, c->enum_basetype);
2013                                                 else if (c->element_class)
2014                                                         retval.data.p = mono_type_get_object (domain, &c->element_class->byval_arg);
2015                                                 else
2016                                                         retval.data.p = NULL;
2017                                         }
2018                                         break;
2019                                 default:
2020                                         ves_exec_method_with_context (&child_frame, context);
2021                                 }
2022                         }
2023
2024                         context->current_frame = frame;
2025
2026                         while (endsp > sp) {
2027                                 --endsp;
2028                                 vt_free (endsp);
2029                         }
2030
2031                         if (child_frame.ex) {
2032                                 /*
2033                                  * An exception occurred, need to run finally, fault and catch handlers..
2034                                  */
2035                                 frame->ex = child_frame.ex;
2036                                 if (context->search_for_handler) {
2037                                         context->search_for_handler = 0;
2038                                         goto handle_exception;
2039                                 }
2040                                 goto handle_finally;
2041                         }
2042
2043                         /* need to handle typedbyref ... */
2044                         if (csignature->ret->type != MONO_TYPE_VOID) {
2045                                 *sp = retval;
2046                                 sp++;
2047                         }
2048                         BREAK;
2049                 }
2050                 CASE (CEE_RET)
2051                         if (signature->ret->type != MONO_TYPE_VOID) {
2052                                 --sp;
2053                                 if (sp->type == VAL_VALUET) {
2054                                         /* the caller has already allocated the memory */
2055                                         stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);
2056                                         vt_free (sp);
2057                                 } else {
2058                                         *frame->retval = *sp;
2059                                 }
2060                         }
2061                         if (sp > frame->stack)
2062                                 g_warning ("more values on stack: %d", sp-frame->stack);
2063
2064                         goto exit_frame;
2065                 CASE (CEE_BR_S) /* Fall through */
2066                 CASE (CEE_BR)
2067                         if (*ip == CEE_BR) {
2068                                 ++ip;
2069                                 ip += (gint32) read32(ip);
2070                                 ip += 4;
2071                         } else {
2072                                 ++ip;
2073                                 ip += (signed char) *ip;
2074                                 ++ip;
2075                         }
2076                         BREAK;
2077                 CASE (CEE_BRFALSE) /* Fall through */
2078                 CASE (CEE_BRFALSE_S) {
2079                         int result;
2080                         int broffset;
2081                         if (*ip == CEE_BRFALSE_S) {
2082                                 broffset = (signed char)ip [1];
2083                                 ip += 2;
2084                         } else {
2085                                 broffset = (gint32) read32 (ip + 1);
2086                                 ip += 5;
2087                         }
2088                         --sp;
2089                         switch (sp->type) {
2090                         case VAL_I32: result = sp->data.i == 0; break;
2091                         case VAL_I64: result = sp->data.l == 0; break;
2092                         case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
2093                         default: result = sp->data.p == NULL; break;
2094                         }
2095                         if (result)
2096                                 ip += broffset;
2097                         BREAK;
2098                 }
2099                 CASE (CEE_BRTRUE) /* Fall through */
2100                 CASE (CEE_BRTRUE_S) {
2101                         int result;
2102                         int broffset;
2103                         if (*ip == CEE_BRTRUE_S) {
2104                                 broffset = (signed char)ip [1];
2105                                 ip += 2;
2106                         } else {
2107                                 broffset = (gint32) read32 (ip + 1);
2108                                 ip += 5;
2109                         }
2110                         --sp;
2111                         switch (sp->type) {
2112                         case VAL_I32: result = sp->data.i != 0; break;
2113                         case VAL_I64: result = sp->data.l != 0; break;
2114                         case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
2115                         default: result = sp->data.p != NULL; break;
2116                         }
2117                         if (result)
2118                                 ip += broffset;
2119                         BREAK;
2120                 }
2121                 CASE (CEE_BEQ) /* Fall through */
2122                 CASE (CEE_BEQ_S) {
2123                         int result;
2124                         int broffset;
2125                         if (*ip == CEE_BEQ_S) {
2126                                 broffset = (signed char)ip [1];
2127                                 ip += 2;
2128                         } else {
2129                                 broffset = (gint32) read32 (ip + 1);
2130                                 ip += 5;
2131                         }
2132                         sp -= 2;
2133                         if (sp->type == VAL_I32)
2134                                 result = (mono_i)sp [0].data.i == (mono_i)GET_NATI (sp [1]);
2135                         else if (sp->type == VAL_I64)
2136                                 result = sp [0].data.l == sp [1].data.l;
2137                         else if (sp->type == VAL_DOUBLE)
2138                                 result = sp [0].data.f == sp [1].data.f;
2139                         else
2140                                 result = sp [0].data.nati == (mono_i)GET_NATI (sp [1]);
2141                         if (result)
2142                                 ip += broffset;
2143                         BREAK;
2144                 }
2145                 CASE (CEE_BGE) /* Fall through */
2146                 CASE (CEE_BGE_S) {
2147                         int result;
2148                         int broffset;
2149                         if (*ip == CEE_BGE_S) {
2150                                 broffset = (signed char)ip [1];
2151                                 ip += 2;
2152                         } else {
2153                                 broffset = (gint32) read32 (ip + 1);
2154                                 ip += 5;
2155                         }
2156                         sp -= 2;
2157                         if (sp->type == VAL_I32)
2158                                 result = (mono_i)sp [0].data.i >= (mono_i)GET_NATI (sp [1]);
2159                         else if (sp->type == VAL_I64)
2160                                 result = sp [0].data.l >= sp [1].data.l;
2161                         else if (sp->type == VAL_DOUBLE)
2162                                 result = sp [0].data.f >= sp [1].data.f;
2163                         else
2164                                 result = (mono_i)sp [0].data.nati >= (mono_i)GET_NATI (sp [1]);
2165                         if (result)
2166                                 ip += broffset;
2167                         BREAK;
2168                 }
2169                 CASE (CEE_BGT) /* Fall through */
2170                 CASE (CEE_BGT_S) {
2171                         int result;
2172                         int broffset;
2173                         if (*ip == CEE_BGT_S) {
2174                                 broffset = (signed char)ip [1];
2175                                 ip += 2;
2176                         } else {
2177                                 broffset = (gint32) read32 (ip + 1);
2178                                 ip += 5;
2179                         }
2180                         sp -= 2;
2181                         if (sp->type == VAL_I32)
2182                                 result = (mono_i)sp [0].data.i > (mono_i)GET_NATI (sp [1]);
2183                         else if (sp->type == VAL_I64)
2184                                 result = sp [0].data.l > sp [1].data.l;
2185                         else if (sp->type == VAL_DOUBLE)
2186                                 result = sp [0].data.f > sp [1].data.f;
2187                         else
2188                                 result = (mono_i)sp [0].data.nati > (mono_i)GET_NATI (sp [1]);
2189                         if (result)
2190                                 ip += broffset;
2191                         BREAK;
2192                 }
2193                 CASE (CEE_BLT) /* Fall through */
2194                 CASE (CEE_BLT_S) {
2195                         int result;
2196                         int broffset;
2197                         if (*ip == CEE_BLT_S) {
2198                                 broffset = (signed char)ip [1];
2199                                 ip += 2;
2200                         } else {
2201                                 broffset = (gint32) read32 (ip + 1);
2202                                 ip += 5;
2203                         }
2204                         sp -= 2;
2205                         if (sp->type == VAL_I32)
2206                                 result = (mono_i)sp[0].data.i < (mono_i)GET_NATI(sp[1]);
2207                         else if (sp->type == VAL_I64)
2208                                 result = sp[0].data.l < sp[1].data.l;
2209                         else if (sp->type == VAL_DOUBLE)
2210                                 result = sp[0].data.f < sp[1].data.f;
2211                         else
2212                                 result = (mono_i)sp[0].data.nati < (mono_i)GET_NATI(sp[1]);
2213                         if (result)
2214                                 ip += broffset;
2215                         BREAK;
2216                 }
2217                 CASE (CEE_BLE) /* fall through */
2218                 CASE (CEE_BLE_S) {
2219                         int result;
2220                         int broffset;
2221                         if (*ip == CEE_BLE_S) {
2222                                 broffset = (signed char)ip [1];
2223                                 ip += 2;
2224                         } else {
2225                                 broffset = (gint32) read32 (ip + 1);
2226                                 ip += 5;
2227                         }
2228                         sp -= 2;
2229
2230                         if (sp->type == VAL_I32)
2231                                 result = (mono_i)sp [0].data.i <= (mono_i)GET_NATI (sp [1]);
2232                         else if (sp->type == VAL_I64)
2233                                 result = sp [0].data.l <= sp [1].data.l;
2234                         else if (sp->type == VAL_DOUBLE)
2235                                 result = sp [0].data.f <= sp [1].data.f;
2236                         else {
2237                                 result = (mono_i)sp [0].data.nati <= (mono_i)GET_NATI (sp [1]);
2238                         }
2239                         if (result)
2240                                 ip += broffset;
2241                         BREAK;
2242                 }
2243                 CASE (CEE_BNE_UN) /* Fall through */
2244                 CASE (CEE_BNE_UN_S) {
2245                         int result;
2246                         int broffset;
2247                         if (*ip == CEE_BNE_UN_S) {
2248                                 broffset = (signed char)ip [1];
2249                                 ip += 2;
2250                         } else {
2251                                 broffset = (gint32) read32 (ip + 1);
2252                                 ip += 5;
2253                         }
2254                         sp -= 2;
2255                         if (sp->type == VAL_I32)
2256                                 result = (mono_u)sp [0].data.i != (mono_u)GET_NATI (sp [1]);
2257                         else if (sp->type == VAL_I64)
2258                                 result = (guint64)sp [0].data.l != (guint64)sp [1].data.l;
2259                         else if (sp->type == VAL_DOUBLE)
2260                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
2261                                         (sp [0].data.f != sp [1].data.f);
2262                         else
2263                                 result = (mono_u)sp [0].data.nati != (mono_u)GET_NATI (sp [1]);
2264                         if (result)
2265                                 ip += broffset;
2266                         BREAK;
2267                 }
2268                 CASE (CEE_BGE_UN) /* Fall through */
2269                 CASE (CEE_BGE_UN_S) {
2270                         int result;
2271                         int broffset;
2272                         if (*ip == CEE_BGE_UN_S) {
2273                                 broffset = (signed char)ip [1];
2274                                 ip += 2;
2275                         } else {
2276                                 broffset = (gint32) read32 (ip + 1);
2277                                 ip += 5;
2278                         }
2279                         sp -= 2;
2280                         if (sp->type == VAL_I32)
2281                                 result = (mono_u)sp [0].data.i >= (mono_u)GET_NATI (sp [1]);
2282                         else if (sp->type == VAL_I64)
2283                                 result = (guint64)sp [0].data.l >= (guint64)sp [1].data.l;
2284                         else if (sp->type == VAL_DOUBLE)
2285                                 result = !isless (sp [0].data.f,sp [1].data.f);
2286                         else
2287                                 result = (mono_u)sp [0].data.nati >= (mono_u)GET_NATI (sp [1]);
2288                         if (result)
2289                                 ip += broffset;
2290                         BREAK;
2291                 }
2292                 CASE (CEE_BGT_UN) /* Fall through */
2293                 CASE (CEE_BGT_UN_S) {
2294                         int result;
2295                         int broffset;
2296                         if (*ip == CEE_BGT_UN_S) {
2297                                 broffset = (signed char)ip [1];
2298                                 ip += 2;
2299                         } else {
2300                                 broffset = (gint32) read32 (ip + 1);
2301                                 ip += 5;
2302                         }
2303                         sp -= 2;
2304                         if (sp->type == VAL_I32)
2305                                 result = (mono_u)sp [0].data.i > (mono_u)GET_NATI (sp [1]);
2306                         else if (sp->type == VAL_I64)
2307                                 result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
2308                         else if (sp->type == VAL_DOUBLE)
2309                                 result = isgreater (sp [0].data.f, sp [1].data.f);
2310                         else
2311                                 result = (mono_u)sp [0].data.nati > (mono_u)GET_NATI (sp [1]);
2312                         if (result)
2313                                 ip += broffset;
2314                         BREAK;
2315                 }
2316                 CASE (CEE_BLE_UN) /* Fall through */
2317                 CASE (CEE_BLE_UN_S) {
2318                         int result;
2319                         int broffset;
2320                         if (*ip == CEE_BLE_UN_S) {
2321                                 broffset = (signed char)ip [1];
2322                                 ip += 2;
2323                         } else {
2324                                 broffset = (gint32) read32 (ip + 1);
2325                                 ip += 5;
2326                         }
2327                         sp -= 2;
2328                         if (sp->type == VAL_I32)
2329                                 result = (mono_u)sp [0].data.i <= (mono_u)GET_NATI (sp [1]);
2330                         else if (sp->type == VAL_I64)
2331                                 result = (guint64)sp [0].data.l <= (guint64)sp [1].data.l;
2332                         else if (sp->type == VAL_DOUBLE)
2333                                 result = islessequal (sp [0].data.f, sp [1].data.f);
2334                         else
2335                                 result = (mono_u)sp [0].data.nati <= (mono_u)GET_NATI (sp [1]);
2336                         if (result)
2337                                 ip += broffset;
2338                         BREAK;
2339                 }
2340                 CASE (CEE_BLT_UN) /* Fall through */
2341                 CASE (CEE_BLT_UN_S) {
2342                         int result;
2343                         int broffset;
2344                         if (*ip == CEE_BLT_UN_S) {
2345                                 broffset = (signed char)ip [1];
2346                                 ip += 2;
2347                         } else {
2348                                 broffset = (gint32) read32 (ip + 1);
2349                                 ip += 5;
2350                         }
2351                         sp -= 2;
2352                         if (sp->type == VAL_I32)
2353                                 result = (mono_u)sp[0].data.i < (mono_u)GET_NATI(sp[1]);
2354                         else if (sp->type == VAL_I64)
2355                                 result = (guint64)sp[0].data.l < (guint64)sp[1].data.l;
2356                         else if (sp->type == VAL_DOUBLE)
2357                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
2358                                         (sp [0].data.f < sp [1].data.f);
2359                         else
2360                                 result = (mono_u)sp[0].data.nati < (mono_u)GET_NATI(sp[1]);
2361                         if (result)
2362                                 ip += broffset;
2363                         BREAK;
2364                 }
2365                 CASE (CEE_SWITCH) {
2366                         guint32 n;
2367                         const unsigned char *st;
2368                         ++ip;
2369                         n = read32 (ip);
2370                         ip += 4;
2371                         st = ip + sizeof (gint32) * n;
2372                         --sp;
2373                         if ((guint32)sp->data.i < n) {
2374                                 gint offset;
2375                                 ip += sizeof (gint32) * (guint32)sp->data.i;
2376                                 offset = read32 (ip);
2377                                 ip = st + offset;
2378                         } else {
2379                                 ip = st;
2380                         }
2381                         BREAK;
2382                 }
2383                 CASE (CEE_LDIND_I1)
2384                         ++ip;
2385                         sp[-1].type = VAL_I32;
2386                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
2387                         BREAK;
2388                 CASE (CEE_LDIND_U1)
2389                         ++ip;
2390                         sp[-1].type = VAL_I32;
2391                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
2392                         BREAK;
2393                 CASE (CEE_LDIND_I2)
2394                         ++ip;
2395                         sp[-1].type = VAL_I32;
2396                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
2397                         BREAK;
2398                 CASE (CEE_LDIND_U2)
2399                         ++ip;
2400                         sp[-1].type = VAL_I32;
2401                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
2402                         BREAK;
2403                 CASE (CEE_LDIND_I4) /* Fall through */
2404                 CASE (CEE_LDIND_U4)
2405                         ++ip;
2406                         sp[-1].type = VAL_I32;
2407                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
2408                         BREAK;
2409                 CASE (CEE_LDIND_I8)
2410                         ++ip;
2411                         sp[-1].type = VAL_I64;
2412                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
2413                         BREAK;
2414                 CASE (CEE_LDIND_I)
2415                         ++ip;
2416                         sp[-1].type = VAL_NATI;
2417                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2418                         BREAK;
2419                 CASE (CEE_LDIND_R4)
2420                         ++ip;
2421                         sp[-1].type = VAL_DOUBLE;
2422                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
2423                         BREAK;
2424                 CASE (CEE_LDIND_R8)
2425                         ++ip;
2426                         sp[-1].type = VAL_DOUBLE;
2427                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
2428                         BREAK;
2429                 CASE (CEE_LDIND_REF)
2430                         ++ip;
2431                         sp[-1].type = VAL_OBJ;
2432                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2433                         BREAK;
2434                 CASE (CEE_STIND_REF) {
2435                         gpointer *p;
2436                         ++ip;
2437                         sp -= 2;
2438                         p = sp->data.p;
2439                         *p = sp[1].data.p;
2440                         BREAK;
2441                 }
2442                 CASE (CEE_STIND_I1) {
2443                         gint8 *p;
2444                         ++ip;
2445                         sp -= 2;
2446                         p = sp->data.p;
2447                         *p = (gint8)sp[1].data.i;
2448                         BREAK;
2449                 }
2450                 CASE (CEE_STIND_I2) {
2451                         gint16 *p;
2452                         ++ip;
2453                         sp -= 2;
2454                         p = sp->data.p;
2455                         *p = (gint16)sp[1].data.i;
2456                         BREAK;
2457                 }
2458                 CASE (CEE_STIND_I4) {
2459                         gint32 *p;
2460                         ++ip;
2461                         sp -= 2;
2462                         p = sp->data.p;
2463                         *p = sp[1].data.i;
2464                         BREAK;
2465                 }
2466                 CASE (CEE_STIND_I) {
2467                         mono_i *p;
2468                         ++ip;
2469                         sp -= 2;
2470                         p = sp->data.p;
2471                         *p = (mono_i)sp[1].data.p;
2472                         BREAK;
2473                 }
2474                 CASE (CEE_STIND_I8) {
2475                         gint64 *p;
2476                         ++ip;
2477                         sp -= 2;
2478                         p = sp->data.p;
2479                         *p = sp[1].data.l;
2480                         BREAK;
2481                 }
2482                 CASE (CEE_STIND_R4) {
2483                         float *p;
2484                         ++ip;
2485                         sp -= 2;
2486                         p = sp->data.p;
2487                         *p = (gfloat)sp[1].data.f;
2488                         BREAK;
2489                 }
2490                 CASE (CEE_STIND_R8) {
2491                         double *p;
2492                         ++ip;
2493                         sp -= 2;
2494                         p = sp->data.p;
2495                         *p = sp[1].data.f;
2496                         BREAK;
2497                 }
2498                 CASE (CEE_ADD)
2499                         ++ip;
2500                         --sp;
2501                         /* should probably consider the pointers as unsigned */
2502                         if (sp->type == VAL_I32) {
2503                                 if (sp [-1].type == VAL_I32)
2504                                         sp [-1].data.i += sp [0].data.i;
2505                                 else
2506                                         sp [-1].data.nati = sp [-1].data.nati + sp [0].data.i;
2507                         } else if (sp->type == VAL_I64)
2508                                 sp [-1].data.l += sp [0].data.l;
2509                         else if (sp->type == VAL_DOUBLE)
2510                                 sp [-1].data.f += sp [0].data.f;
2511                         else {
2512                                 if (sp [-1].type == VAL_I32) {
2513                                         sp [-1].data.nati = sp [-1].data.i + sp [0].data.nati;
2514                                         sp [-1].type = sp [0].type;
2515                                 } else
2516                                         sp [-1].data.nati = sp [-1].data.nati + sp [0].data.nati;
2517                         }
2518                         BREAK;
2519                 CASE (CEE_SUB)
2520                         ++ip;
2521                         --sp;
2522                         /* should probably consider the pointers as unsigned */
2523                         if (sp->type == VAL_I32) {
2524                                 if (sp [-1].type == VAL_I32)
2525                                         sp [-1].data.i -= sp [0].data.i;
2526                                 else {
2527                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.i;
2528                                         sp [-1].type = VAL_NATI;
2529                                 }
2530                         } else if (sp->type == VAL_I64)
2531                                 sp [-1].data.l -= sp [0].data.l;
2532                         else if (sp->type == VAL_DOUBLE)
2533                                 sp [-1].data.f -= sp [0].data.f;
2534                         else {
2535                                 if (sp [-1].type == VAL_I32) {
2536                                         sp [-1].data.nati = sp [-1].data.i - sp [0].data.nati;
2537                                         sp [-1].type = sp [0].type;
2538                                 } else
2539                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.nati;
2540                         }
2541                         BREAK;
2542                 CASE (CEE_MUL)
2543                         ++ip;
2544                         --sp;
2545                         if (sp->type == VAL_I32) {
2546                                 if (sp [-1].type == VAL_I32)
2547                                         sp [-1].data.i *= sp [0].data.i;
2548                                 else
2549                                         sp [-1].data.nati = sp [-1].data.nati * sp [0].data.i;
2550                         } else if (sp->type == VAL_I64)
2551                                 sp [-1].data.l *= sp [0].data.l;
2552                         else if (sp->type == VAL_DOUBLE)
2553                                 sp [-1].data.f *= sp [0].data.f;
2554                         else {
2555                                 if (sp [-1].type == VAL_NATI)
2556                                         sp [-1].data.nati = sp [-1].data.nati * sp [0].data.nati;
2557                                 else {
2558                                         sp [-1].data.nati = sp [-1].data.i * sp [0].data.nati;
2559                                         sp [-1].type = VAL_NATI;
2560                                 }
2561                         }
2562                         BREAK;
2563                 CASE (CEE_DIV)
2564                         ++ip;
2565                         --sp;
2566                         if (sp->type == VAL_I32) {
2567                                 if (sp [0].data.i == 0)
2568                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2569                                 if (sp [-1].type == VAL_I32)
2570                                         sp [-1].data.i /= sp [0].data.i;
2571                                 else
2572                                         sp [-1].data.nati /= sp [0].data.i;
2573                         } else if (sp->type == VAL_I64) {
2574                                 if (sp [0].data.l == 0)
2575                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2576                                 sp [-1].data.l /= sp [0].data.l;
2577                         } else if (sp->type == VAL_DOUBLE) {
2578                                 /* set NaN is divisor is 0.0 */
2579                                 sp [-1].data.f /= sp [0].data.f;
2580                         } else {
2581                                 if (sp [-1].type == VAL_NATI)
2582                                         sp [-1].data.nati = sp [-1].data.nati / sp [0].data.nati;
2583                                 else {
2584                                         sp [-1].data.nati = sp [-1].data.i / sp [0].data.nati;
2585                                         sp [-1].type = VAL_NATI;
2586                                 }
2587                         }
2588                         BREAK;
2589                 CASE (CEE_DIV_UN)
2590                         ++ip;
2591                         --sp;
2592                         if (sp->type == VAL_I32) {
2593                                 if (sp [0].data.i == 0)
2594                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2595                                 if (sp [-1].type == VAL_NATI)
2596                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati / (mono_u)sp [0].data.i;
2597                                 else
2598                                         sp [-1].data.i = (guint32)sp [-1].data.i / (guint32)sp [0].data.i;
2599                         } else if (sp->type == VAL_I64) {
2600                                 guint64 val;
2601                                 if (sp [0].data.l == 0)
2602                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2603                                 val = sp [-1].data.l;
2604                                 val /= (guint64)sp [0].data.l;
2605                                 sp [-1].data.l = val;
2606                         } else {
2607                                 if (sp [0].data.nati == 0)
2608                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2609                                 if (sp [-1].type == VAL_NATI)
2610                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati / (mono_u)sp [0].data.nati;
2611                                 else {
2612                                         sp [-1].data.nati = (mono_u)sp [-1].data.i / (mono_u)sp [0].data.nati;
2613                                         sp [-1].type = VAL_NATI;
2614                                 }
2615                         }
2616                         BREAK;
2617                 CASE (CEE_REM)
2618                         ++ip;
2619                         --sp;
2620                         if (sp->type == VAL_I32) {
2621                                 if (sp [0].data.i == 0)
2622                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2623                                 if (sp [-1].type == VAL_NATI)
2624                                         sp [-1].data.nati = (mono_i)sp [-1].data.nati % (mono_i)sp [0].data.i;
2625                                 else
2626                                         sp [-1].data.i = sp [-1].data.i % sp [0].data.i;
2627                         } else if (sp->type == VAL_I64) {
2628                                 if (sp [0].data.l == 0)
2629                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2630                                 sp [-1].data.l %= sp [0].data.l;
2631                         } else if (sp->type == VAL_DOUBLE) {
2632                                 /* FIXME: what do we actually do here? */
2633                                 sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
2634                         } else {
2635                                 if (sp [0].data.nati == 0)
2636                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2637                                 if (sp [-1].type == VAL_NATI)
2638                                         sp [-1].data.nati = (mono_i)sp [-1].data.nati % (mono_i)sp [0].data.nati;
2639                                 else {
2640                                         sp [-1].data.nati = (mono_i)sp [-1].data.i % (mono_i)sp [0].data.nati;
2641                                         sp [-1].type = VAL_NATI;
2642                                 }
2643                         }
2644                         BREAK;
2645                 CASE (CEE_REM_UN)
2646                         ++ip;
2647                         --sp;
2648                         if (sp->type == VAL_I32) {
2649                                 if (sp [0].data.i == 0)
2650                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2651                                 if (sp [-1].type == VAL_NATI)
2652                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati % (mono_u)sp [0].data.i;
2653                                 else
2654                                         sp [-1].data.i = (guint32)sp [-1].data.i % (guint32)sp [0].data.i;
2655                         } else if (sp->type == VAL_I64) {
2656                                 if (sp [0].data.l == 0)
2657                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2658                                 sp [-1].data.l = (guint64)sp [-1].data.l % (guint64)sp [0].data.l;
2659                         } else if (sp->type == VAL_DOUBLE) {
2660                                 /* unspecified behaviour according to the spec */
2661                         } else {
2662                                 if (sp [0].data.nati == 0)
2663                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2664                                 if (sp [-1].type == VAL_NATI)
2665                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati % (mono_u)sp [0].data.nati;
2666                                 else {
2667                                         sp [-1].data.nati = (mono_u)sp [-1].data.i % (mono_u)sp [0].data.nati;
2668                                         sp [-1].type = VAL_NATI;
2669                                 }
2670                         }
2671                         BREAK;
2672                 CASE (CEE_AND)
2673                         ++ip;
2674                         --sp;
2675                         if (sp->type == VAL_I32) {
2676                                 if (sp [-1].type == VAL_NATI)
2677                                         sp [-1].data.nati &= sp [0].data.i;
2678                                 else
2679                                         sp [-1].data.i &= sp [0].data.i;
2680                         }
2681                         else if (sp->type == VAL_I64)
2682                                 sp [-1].data.l &= sp [0].data.l;
2683                         else {
2684                                 if (sp [-1].type == VAL_NATI)
2685                                         sp [-1].data.nati = (mono_i)sp [-1].data.nati & (mono_i)sp [0].data.nati;
2686                                 else {
2687                                         sp [-1].data.nati = (mono_i)sp [-1].data.i & (mono_i)sp [0].data.nati;
2688                                         sp [-1].type = VAL_NATI;
2689                                 }
2690                         }
2691                         BREAK;
2692                 CASE (CEE_OR)
2693                         ++ip;
2694                         --sp;
2695                         if (sp->type == VAL_I32) {
2696                                 if (sp [-1].type == VAL_NATI)
2697                                         sp [-1].data.nati |= sp [0].data.i;
2698                                 else
2699                                         sp [-1].data.i |= sp [0].data.i;
2700                         }
2701                         else if (sp->type == VAL_I64)
2702                                 sp [-1].data.l |= sp [0].data.l;
2703                         else {
2704                                 if (sp [-1].type == VAL_NATI)
2705                                         sp [-1].data.nati = (mono_i)sp [-1].data.nati | (mono_i)sp [0].data.nati;
2706                                 else {
2707                                         sp [-1].data.nati = (mono_i)sp [-1].data.i | (mono_i)sp [0].data.nati;
2708                                         sp [-1].type = VAL_NATI;
2709                                 }
2710                         }
2711                         BREAK;
2712                 CASE (CEE_XOR)
2713                         ++ip;
2714                         --sp;
2715                         if (sp->type == VAL_I32) {
2716                                 if (sp [-1].type == VAL_NATI)
2717                                         sp [-1].data.nati ^= sp [0].data.i;
2718                                 else
2719                                         sp [-1].data.i ^= sp [0].data.i;
2720                         }
2721                         else if (sp->type == VAL_I64)
2722                                 sp [-1].data.l ^= sp [0].data.l;
2723                         else {
2724                                 if (sp [-1].type == VAL_NATI)
2725                                         sp [-1].data.nati = (mono_i)sp [-1].data.nati ^ (mono_i)sp [0].data.nati;
2726                                 else {
2727                                         sp [-1].data.nati = (mono_i)sp [-1].data.i ^ (mono_i)sp [0].data.nati;
2728                                         sp [-1].type = VAL_NATI;
2729                                 }
2730                         }
2731                         BREAK;
2732                 CASE (CEE_SHL)
2733                         ++ip;
2734                         --sp;
2735                         if (sp [-1].type == VAL_I32)
2736                                 sp [-1].data.i <<= GET_NATI (sp [0]);
2737                         else if (sp [-1].type == VAL_I64)
2738                                 sp [-1].data.l <<= GET_NATI (sp [0]);
2739                         else
2740                                 sp [-1].data.nati <<= GET_NATI (sp [0]);
2741                         BREAK;
2742                 CASE (CEE_SHR)
2743                         ++ip;
2744                         --sp;
2745                         if (sp [-1].type == VAL_I32)
2746                                 sp [-1].data.i >>= GET_NATI (sp [0]);
2747                         else if (sp [-1].type == VAL_I64)
2748                                 sp [-1].data.l >>= GET_NATI (sp [0]);
2749                         else
2750                                 sp [-1].data.nati = ((mono_i)sp [-1].data.nati) >> GET_NATI (sp [0]);
2751                         BREAK;
2752                 CASE (CEE_SHR_UN)
2753                         ++ip;
2754                         --sp;
2755                         if (sp [-1].type == VAL_I32)
2756                                 sp [-1].data.i = (guint)sp [-1].data.i >> GET_NATI (sp [0]);
2757                         else if (sp [-1].type == VAL_I64)
2758                                 sp [-1].data.l = (guint64)sp [-1].data.l >> GET_NATI (sp [0]);
2759                         else
2760                                 sp [-1].data.nati = ((mono_u)sp[-1].data.nati) >> GET_NATI (sp [0]);
2761                         BREAK;
2762                 CASE (CEE_NEG)
2763                         ++ip;
2764                         --sp;
2765                         if (sp->type == VAL_I32) 
2766                                 sp->data.i = - sp->data.i;
2767                         else if (sp->type == VAL_I64)
2768                                 sp->data.l = - sp->data.l;
2769                         else if (sp->type == VAL_DOUBLE)
2770                                 sp->data.f = - sp->data.f;
2771                         else if (sp->type == VAL_NATI)
2772                                 sp->data.nati = - (mono_i)sp->data.nati;
2773                         ++sp;
2774                         BREAK;
2775                 CASE (CEE_NOT)
2776                         ++ip;
2777                         --sp;
2778                         if (sp->type == VAL_I32)
2779                                 sp->data.i = ~ sp->data.i;
2780                         else if (sp->type == VAL_I64)
2781                                 sp->data.l = ~ sp->data.l;
2782                         else if (sp->type == VAL_NATI)
2783                                 sp->data.nati = ~ (mono_i)sp->data.p;
2784                         ++sp;
2785                         BREAK;
2786                 CASE (CEE_CONV_U1) {
2787                         ++ip;
2788                         switch (sp [-1].type) {
2789                         case VAL_DOUBLE:
2790                                 sp [-1].data.i = (guint8)sp [-1].data.f;
2791                                 break;
2792                         case VAL_I64:
2793                                 sp [-1].data.i = (guint8)sp [-1].data.l;
2794                                 break;
2795                         case VAL_VALUET:
2796                                 ves_abort();
2797                         case VAL_I32:
2798                                 sp [-1].data.i = (guint8)sp [-1].data.i;
2799                                 break;
2800                         default:
2801                                 sp [-1].data.i = (guint8)sp [-1].data.nati;
2802                                 break;
2803                         }
2804                         sp [-1].type = VAL_I32;
2805                         BREAK;
2806                 }
2807                 CASE (CEE_CONV_I1) {
2808                         ++ip;
2809                         switch (sp [-1].type) {
2810                         case VAL_DOUBLE:
2811                                 sp [-1].data.i = (gint8)sp [-1].data.f;
2812                                 break;
2813                         case VAL_I64:
2814                                 sp [-1].data.i = (gint8)sp [-1].data.l;
2815                                 break;
2816                         case VAL_VALUET:
2817                                 ves_abort();
2818                         case VAL_I32:
2819                                 sp [-1].data.i = (gint8)sp [-1].data.i;
2820                                 break;
2821                         default:
2822                                 sp [-1].data.i = (gint8)sp [-1].data.nati;
2823                                 break;
2824                         }
2825                         sp [-1].type = VAL_I32;
2826                         BREAK;
2827                 }
2828                 CASE (CEE_CONV_U2) {
2829                         ++ip;
2830                         switch (sp [-1].type) {
2831                         case VAL_DOUBLE:
2832                                 sp [-1].data.i = (guint16)sp [-1].data.f;
2833                                 break;
2834                         case VAL_I64:
2835                                 sp [-1].data.i = (guint16)sp [-1].data.l;
2836                                 break;
2837                         case VAL_VALUET:
2838                                 ves_abort();
2839                         case VAL_I32:
2840                                 sp [-1].data.i = (guint16)sp [-1].data.i;
2841                                 break;
2842                         default:
2843                                 sp [-1].data.i = (guint16)sp [-1].data.nati;
2844                                 break;
2845                         }
2846                         sp [-1].type = VAL_I32;
2847                         BREAK;
2848                 }
2849                 CASE (CEE_CONV_I2) {
2850                         ++ip;
2851                         switch (sp [-1].type) {
2852                         case VAL_DOUBLE:
2853                                 sp [-1].data.i = (gint16)sp [-1].data.f;
2854                                 break;
2855                         case VAL_I64:
2856                                 sp [-1].data.i = (gint16)sp [-1].data.l;
2857                                 break;
2858                         case VAL_VALUET:
2859                                 ves_abort();
2860                         case VAL_I32:
2861                                 sp [-1].data.i = (gint16)sp [-1].data.i;
2862                                 break;
2863                         default:
2864                                 sp [-1].data.i = (gint16)sp [-1].data.nati;
2865                                 break;
2866                         }
2867                         sp [-1].type = VAL_I32;
2868                         BREAK;
2869                 }
2870                 CASE (CEE_CONV_U4) /* Fall through */
2871 #if SIZEOF_VOID_P == 4
2872                 CASE (CEE_CONV_I) /* Fall through */
2873                 CASE (CEE_CONV_U) /* Fall through */
2874 #endif
2875                 CASE (CEE_CONV_I4) {
2876                         ++ip;
2877                         switch (sp [-1].type) {
2878                         case VAL_DOUBLE:
2879                                 sp [-1].data.i = (gint32)sp [-1].data.f;
2880                                 break;
2881                         case VAL_I64:
2882                                 sp [-1].data.i = (gint32)sp [-1].data.l;
2883                                 break;
2884                         case VAL_VALUET:
2885                                 ves_abort();
2886                         case VAL_I32:
2887                                 break;
2888                         default:
2889                                 sp [-1].data.i = (gint32)sp [-1].data.p;
2890                                 break;
2891                         }
2892                         sp [-1].type = VAL_I32;
2893                         BREAK;
2894                 }
2895 #if SIZEOF_VOID_P == 8
2896                 CASE (CEE_CONV_I) /* Fall through */
2897 #endif
2898                 CASE (CEE_CONV_I8)
2899                         ++ip;
2900                         switch (sp [-1].type) {
2901                         case VAL_DOUBLE:
2902                                 sp [-1].data.l = (gint64)sp [-1].data.f;
2903                                 break;
2904                         case VAL_I64:
2905                                 break;
2906                         case VAL_VALUET:
2907                                 ves_abort();
2908                         case VAL_I32:
2909                                 sp [-1].data.l = (gint64)sp [-1].data.i;
2910                                 break;
2911                         default:
2912                                 sp [-1].data.l = (gint64)sp [-1].data.nati;
2913                                 break;
2914                         }
2915                         sp [-1].type = ip[-1] == CEE_CONV_I ? VAL_NATI : VAL_I64;
2916                         BREAK;
2917                 CASE (CEE_CONV_R4) {
2918                         ++ip;
2919                         switch (sp [-1].type) {
2920                         case VAL_DOUBLE:
2921                                 sp [-1].data.f = (float)sp [-1].data.f;
2922                                 break;
2923                         case VAL_I64:
2924                                 sp [-1].data.f = (float)sp [-1].data.l;
2925                                 break;
2926                         case VAL_VALUET:
2927                                 ves_abort();
2928                         case VAL_I32:
2929                                 sp [-1].data.f = (float)sp [-1].data.i;
2930                                 break;
2931                         default:
2932                                 sp [-1].data.f = (float)sp [-1].data.nati;
2933                                 break;
2934                         }
2935                         sp [-1].type = VAL_DOUBLE;
2936                         BREAK;
2937                 }
2938                 CASE (CEE_CONV_R8) {
2939                         ++ip;
2940                         switch (sp [-1].type) {
2941                         case VAL_DOUBLE:
2942                                 sp [-1].data.f = (double)sp [-1].data.f;
2943                                 break;
2944                         case VAL_I64:
2945                                 sp [-1].data.f = (double)sp [-1].data.l;
2946                                 break;
2947                         case VAL_VALUET:
2948                                 ves_abort();
2949                         case VAL_I32:
2950                                 sp [-1].data.f = (double)sp [-1].data.i;
2951                                 break;
2952                         default:
2953                                 sp [-1].data.f = (double)sp [-1].data.nati;
2954                                 break;
2955                         }
2956                         sp [-1].type = VAL_DOUBLE;
2957                         BREAK;
2958                 }
2959 #if SIZEOF_VOID_P == 8
2960                 CASE (CEE_CONV_U) /* Fall through */
2961 #endif
2962                 CASE (CEE_CONV_U8)
2963                         ++ip;
2964
2965                         switch (sp [-1].type){
2966                         case VAL_DOUBLE:
2967                                 sp [-1].data.l = (guint64)sp [-1].data.f;
2968                                 break;
2969                         case VAL_I64:
2970                                 break;
2971                         case VAL_VALUET:
2972                                 ves_abort();
2973                         case VAL_I32:
2974                                 sp [-1].data.l = sp [-1].data.i & 0xffffffff;
2975                                 break;
2976                         default:
2977                                 sp [-1].data.l = (guint64) sp [-1].data.nati;
2978                                 break;
2979                         }
2980                         sp [-1].type = ip[-1] == CEE_CONV_U ? VAL_NATI : VAL_I64;
2981                         BREAK;
2982                 CASE (CEE_CPOBJ) {
2983                         MonoClass *vtklass;
2984                         ++ip;
2985                         vtklass = mono_class_get (image, read32 (ip));
2986                         ip += 4;
2987                         sp -= 2;
2988                         memcpy (sp [0].data.p, sp [1].data.p, mono_class_value_size (vtklass, NULL));
2989                         BREAK;
2990                 }
2991                 CASE (CEE_LDOBJ) {
2992                         guint32 token;
2993                         MonoClass *c;
2994                         char *addr;
2995
2996                         ++ip;
2997                         token = read32 (ip);
2998                         ip += 4;
2999
3000                         if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
3001                                 c = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
3002                         else
3003                                 c = mono_class_get (image, token);
3004
3005                         addr = sp [-1].data.vt;
3006                         vt_alloc (&c->byval_arg, &sp [-1], FALSE);
3007                         stackval_from_data (&c->byval_arg, &sp [-1], addr, FALSE);
3008                         BREAK;
3009                 }
3010                 CASE (CEE_LDSTR) {
3011                         MonoObject *o;
3012                         guint32 str_index;
3013
3014                         ip++;
3015                         str_index = mono_metadata_token_index (read32 (ip));
3016                         ip += 4;
3017
3018                         if (frame->method->wrapper_type != MONO_WRAPPER_NONE) {
3019                                 o = (MonoObject *)mono_string_new_wrapper(
3020                                         mono_method_get_wrapper_data (frame->method, str_index));
3021                         }
3022                         else
3023                                 o = (MonoObject*)mono_ldstr (domain, image, str_index);
3024                         sp->type = VAL_OBJ;
3025                         sp->data.p = o;
3026
3027                         ++sp;
3028                         BREAK;
3029                 }
3030                 CASE (CEE_NEWOBJ) {
3031                         MonoObject *o;
3032                         MonoClass *newobj_class;
3033                         MonoMethodSignature *csig;
3034                         stackval valuetype_this;
3035                         stackval *endsp = sp;
3036                         guint32 token;
3037                         stackval retval;
3038
3039                         frame->ip = ip;
3040
3041                         ip++;
3042                         token = read32 (ip);
3043                         ip += 4;
3044
3045                         if (!(child_frame.method = mono_get_method (image, token, NULL)))
3046                                 THROW_EX (mono_get_exception_missing_method (), ip -5);
3047
3048                         csig = child_frame.method->signature;
3049                         newobj_class = child_frame.method->klass;
3050                         /*if (profiling_classes) {
3051                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
3052                                 count++;
3053                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
3054                         }*/
3055                                 
3056
3057                         if (newobj_class->parent == mono_defaults.array_class) {
3058                                 sp -= csig->param_count;
3059                                 o = ves_array_create (domain, newobj_class, csig, sp);
3060                                 goto array_constructed;
3061                         }
3062
3063                         /*
3064                          * First arg is the object.
3065                          */
3066                         if (newobj_class->valuetype) {
3067                                 void *zero;
3068                                 vt_alloc (&newobj_class->byval_arg, &valuetype_this, csig->pinvoke);
3069                                 if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
3070                                         zero = valuetype_this.data.vt;
3071                                         child_frame.obj = valuetype_this.data.vt;
3072                                 } else {
3073                                         memset (&valuetype_this, 0, sizeof (stackval));
3074                                         zero = &valuetype_this;
3075                                         child_frame.obj = &valuetype_this;
3076                                 }
3077                                 stackval_from_data (&newobj_class->byval_arg, &valuetype_this, zero, csig->pinvoke);
3078                         } else {
3079                                 if (newobj_class != mono_defaults.string_class) {
3080                                         o = mono_object_new (domain, newobj_class);
3081                                         child_frame.obj = o;
3082                                 } else {
3083                                         child_frame.retval = &retval;
3084                                 }
3085                         }
3086
3087                         if (csig->param_count) {
3088                                 sp -= csig->param_count;
3089                                 child_frame.stack_args = sp;
3090                         } else {
3091                                 child_frame.stack_args = NULL;
3092                         }
3093
3094                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
3095
3096                         child_frame.ip = NULL;
3097                         child_frame.ex = NULL;
3098                         child_frame.ex_handler = NULL;
3099
3100                         ves_exec_method_with_context (&child_frame, context);
3101
3102                         context->current_frame = frame;
3103
3104                         while (endsp > sp) {
3105                                 --endsp;
3106                                 vt_free (endsp);
3107                         }
3108
3109                         if (child_frame.ex) {
3110                                 /*
3111                                  * An exception occurred, need to run finally, fault and catch handlers..
3112                                  */
3113                                 frame->ex = child_frame.ex;
3114                                 goto handle_finally;
3115                         }
3116                         /*
3117                          * a constructor returns void, but we need to return the object we created
3118                          */
3119 array_constructed:
3120                         if (newobj_class->valuetype && !newobj_class->enumtype) {
3121                                 *sp = valuetype_this;
3122                         } else if (newobj_class == mono_defaults.string_class) {
3123                                 *sp = retval;
3124                         } else {
3125                                 sp->type = VAL_OBJ;
3126                                 sp->data.p = o;
3127                         }
3128                         ++sp;
3129                         BREAK;
3130                 }
3131                 CASE (CEE_CASTCLASS) /* Fall through */
3132                 CASE (CEE_ISINST) {
3133                         MonoObject *o;
3134                         MonoClass *c;
3135                         guint32 token;
3136                         int do_isinst = *ip == CEE_ISINST;
3137
3138                         ++ip;
3139                         token = read32 (ip);
3140                         c = mono_class_get (image, token);
3141
3142                         g_assert (sp [-1].type == VAL_OBJ);
3143
3144                         if ((o = sp [-1].data.p)) {
3145                                 if (!mono_object_isinst (o, c)) {
3146                                         if (do_isinst) {
3147                                                 sp [-1].data.p = NULL;
3148                                         } else
3149                                                 THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
3150                                 }
3151                         }
3152                         ip += 4;
3153                         BREAK;
3154                 }
3155                 CASE (CEE_CONV_R_UN)
3156                         ++ip;
3157                         switch (sp [-1].type) {
3158                         case VAL_DOUBLE:
3159                                 break;
3160                         case VAL_I64:
3161                                 sp [-1].data.f = (double)(guint64)sp [-1].data.l;
3162                                 break;
3163                         case VAL_VALUET:
3164                                 ves_abort();
3165                         case VAL_I32:
3166                                 sp [-1].data.f = (double)(guint32)sp [-1].data.i;
3167                                 break;
3168                         default:
3169                                 sp [-1].data.f = (double)(guint64)sp [-1].data.nati;
3170                                 break;
3171                         }
3172                         sp [-1].type = VAL_DOUBLE;
3173                         BREAK;
3174                 CASE (CEE_UNUSED58)
3175                 CASE (CEE_UNUSED1) ves_abort(); BREAK;
3176                 CASE (CEE_UNBOX) {
3177                         MonoObject *o;
3178                         MonoClass *c;
3179                         guint32 token;
3180
3181                         ++ip;
3182                         token = read32 (ip);
3183                         
3184                         if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
3185                                 c = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
3186                         else 
3187                                 c = mono_class_get (image, token);
3188                         
3189                         o = sp [-1].data.p;
3190                         if (!o)
3191                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
3192
3193                         if (!(mono_object_isinst (o, c) || 
3194                                   ((o->vtable->klass->rank == 0) && 
3195                                    (o->vtable->klass->element_class == c->element_class))))
3196                                 THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
3197
3198                         sp [-1].type = VAL_MP;
3199                         sp [-1].data.p = (char *)o + sizeof (MonoObject);
3200
3201                         ip += 4;
3202                         BREAK;
3203                 }
3204                 CASE (CEE_THROW)
3205                         --sp;
3206                         frame->ex_handler = NULL;
3207                         if (!sp->data.p)
3208                                 sp->data.p = mono_get_exception_null_reference ();
3209                         THROW_EX ((MonoException *)sp->data.p, ip);
3210                         BREAK;
3211                 CASE (CEE_LDFLDA) /* Fall through */
3212                 CASE (CEE_LDFLD) {
3213                         MonoObject *obj;
3214                         MonoClassField *field;
3215                         guint32 token;
3216                         int load_addr = *ip == CEE_LDFLDA;
3217                         char *addr;
3218
3219                         if (!sp [-1].data.p)
3220                                 THROW_EX (mono_get_exception_null_reference (), ip);
3221                         
3222                         ++ip;
3223                         token = read32 (ip);
3224                         field = rtd->field_info[token].field;
3225                         ip += 4;
3226
3227                         if (sp [-1].type == VAL_OBJ) {
3228                                 obj = sp [-1].data.p;
3229                                 if (obj->vtable->klass == mono_defaults.transparent_proxy_class && field->parent->marshalbyref) {
3230                                         MonoClass *klass = ((MonoTransparentProxy*)obj)->klass;
3231                                         addr = mono_load_remote_field (obj, klass, field, NULL);
3232                                 } else {
3233                                         addr = (char*)obj + field->offset;
3234                                 }                               
3235                         } else {
3236                                 obj = sp [-1].data.vt;
3237                                 addr = (char*)obj + field->offset - sizeof (MonoObject);
3238                         }
3239
3240                         if (load_addr) {
3241                                 sp [-1].type = VAL_MP;
3242                                 sp [-1].data.p = addr;
3243                         } else {
3244                                 vt_alloc (field->type, &sp [-1], FALSE);
3245                                 stackval_from_data (field->type, &sp [-1], addr, FALSE);                                
3246                         }
3247                         BREAK;
3248                 }
3249                 CASE (CEE_STFLD) {
3250                         MonoObject *obj;
3251                         MonoClassField *field;
3252                         guint32 token, offset;
3253
3254                         sp -= 2;
3255                         
3256                         if (!sp [0].data.p)
3257                                 THROW_EX (mono_get_exception_null_reference (), ip);
3258                         
3259                         ++ip;
3260                         token = read32 (ip);
3261                         field = rtd->field_info[token].field;
3262                         ip += 4;
3263                         
3264                         if (sp [0].type == VAL_OBJ) {
3265                                 obj = sp [0].data.p;
3266
3267                                 if (obj->vtable->klass == mono_defaults.transparent_proxy_class && field->parent->marshalbyref) {
3268                                         MonoClass *klass = ((MonoTransparentProxy*)obj)->klass;
3269                                         mono_store_remote_field (obj, klass, field, &sp [1].data);
3270                                 } else {
3271                                         offset = field->offset;
3272                                         stackval_to_data (field->type, &sp [1], (char*)obj + offset, FALSE);
3273                                         vt_free (&sp [1]);
3274                                 }
3275                         } else {
3276                                 obj = sp [0].data.vt;
3277                                 offset = field->offset - sizeof (MonoObject);
3278                                 stackval_to_data (field->type, &sp [1], (char*)obj + offset, FALSE);
3279                                 vt_free (&sp [1]);
3280                         }
3281
3282                         BREAK;
3283                 }
3284                 CASE (CEE_LDSFLD) /* Fall through */
3285                 CASE (CEE_LDSFLDA) {
3286                         MonoVTable *vt;
3287                         MonoClassField *field;
3288                         guint32 token;
3289                         int load_addr = *ip == CEE_LDSFLDA;
3290                         gpointer addr;
3291
3292                         ++ip;
3293                         token = read32 (ip);
3294                         field = rtd->field_info[token].field;
3295                         ip += 4;
3296                                                 
3297                         vt = mono_class_vtable (domain, field->parent);
3298                         if (!vt->initialized)
3299                                 mono_runtime_class_init (vt);
3300                         if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
3301                                 addr = (char*)(vt->data) + field->offset;
3302                         else
3303                                 addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
3304
3305                         if (load_addr) {
3306                                 sp->type = VAL_MP;
3307                                 sp->data.p = addr;
3308                         } else {
3309                                 vt_alloc (field->type, sp, FALSE);
3310                                 stackval_from_data (field->type, sp, addr, FALSE);
3311                         }
3312                         ++sp;
3313                         BREAK;
3314                 }
3315                 CASE (CEE_STSFLD) {
3316                         MonoVTable *vt;
3317                         MonoClassField *field;
3318                         guint32 token;
3319                         gpointer addr;
3320
3321                         ++ip;
3322                         token = read32 (ip);
3323                         field = rtd->field_info[token].field;
3324                         ip += 4;
3325                         --sp;
3326
3327                         vt = mono_class_vtable (domain, field->parent);
3328                         if (!vt->initialized)
3329                                 mono_runtime_class_init (vt);
3330                         if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
3331                                 addr = (char*)(vt->data) + field->offset;
3332                         else
3333                                 addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
3334
3335                         stackval_to_data (field->type, sp, addr, FALSE);
3336                         vt_free (sp);
3337                         BREAK;
3338                 }
3339                 CASE (CEE_STOBJ) {
3340                         MonoClass *vtklass;
3341                         ++ip;
3342                         vtklass = mono_class_get (image, read32 (ip));
3343                         ip += 4;
3344                         sp -= 2;
3345
3346                         /*
3347                          * LAMESPEC: According to the spec, the stack should contain a 
3348                          * pointer to a value type. In reality, it can contain anything.
3349                          */
3350                         if (sp [1].type == VAL_VALUET)
3351                                 memcpy (sp [0].data.p, sp [1].data.vt, mono_class_value_size (vtklass, NULL));
3352                         else
3353                                 memcpy (sp [0].data.p, &sp [1].data, mono_class_value_size (vtklass, NULL));
3354                         BREAK;
3355                 }
3356 #if SIZEOF_VOID_P == 8
3357                 CASE (CEE_CONV_OVF_I_UN)
3358 #endif
3359                 CASE (CEE_CONV_OVF_I8_UN) {
3360                         switch (sp [-1].type) {
3361                         case VAL_DOUBLE:
3362                                 if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807LL)
3363                                         THROW_EX (mono_get_exception_overflow (), ip);
3364                                 sp [-1].data.l = (guint64)sp [-1].data.f;
3365                                 break;
3366                         case VAL_I64:
3367                                 break;
3368                         case VAL_VALUET:
3369                                 ves_abort();
3370                         case VAL_I32:
3371                                 /* Can't overflow */
3372                                 sp [-1].data.l = (guint64)sp [-1].data.i;
3373                                 break;
3374                         default:
3375                                 sp [-1].data.l = (guint64)sp [-1].data.nati;
3376                                 break;
3377                         }
3378                         sp [-1].type = VAL_I64;
3379                         ++ip;
3380                         BREAK;
3381                 }
3382 #if SIZEOF_VOID_P == 8
3383                 CASE (CEE_CONV_OVF_U_UN) 
3384 #endif
3385                 CASE (CEE_CONV_OVF_U8_UN) {
3386                         switch (sp [-1].type) {
3387                         case VAL_DOUBLE:
3388                                 if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT64_MAX)
3389                                         THROW_EX (mono_get_exception_overflow (), ip);
3390                                 sp [-1].data.l = (guint64)sp [-1].data.f;
3391                                 break;
3392                         case VAL_I64:
3393                                 /* nothing to do */
3394                                 break;
3395                         case VAL_VALUET:
3396                                 ves_abort();
3397                         case VAL_I32:
3398                                 /* Can't overflow */
3399                                 sp [-1].data.l = (guint64)sp [-1].data.i;
3400                                 break;
3401                         default:
3402                                 /* Can't overflow */
3403                                 sp [-1].data.l = (guint64)sp [-1].data.nati;
3404                                 break;
3405                         }
3406                         sp [-1].type = VAL_I64;
3407                         ++ip;
3408                         BREAK;
3409                 }
3410 #if SIZEOF_VOID_P == 4
3411                 CASE (CEE_CONV_OVF_I_UN)
3412                 CASE (CEE_CONV_OVF_U_UN) 
3413 #endif
3414                 CASE (CEE_CONV_OVF_I1_UN)
3415                 CASE (CEE_CONV_OVF_I2_UN)
3416                 CASE (CEE_CONV_OVF_I4_UN)
3417                 CASE (CEE_CONV_OVF_U1_UN)
3418                 CASE (CEE_CONV_OVF_U2_UN)
3419                 CASE (CEE_CONV_OVF_U4_UN) {
3420                         guint64 value;
3421                         switch (sp [-1].type) {
3422                         case VAL_DOUBLE:
3423                                 if (sp [-1].data.f <= -1.0)
3424                                         THROW_EX (mono_get_exception_overflow (), ip);
3425                                 value = (guint64)sp [-1].data.f;
3426                                 break;
3427                         case VAL_I64:
3428                                 value = (guint64)sp [-1].data.l;
3429                                 break;
3430                         case VAL_VALUET:
3431                                 ves_abort();
3432                         case VAL_I32:
3433                                 value = (guint64)sp [-1].data.i;
3434                                 break;
3435                         default:
3436                                 value = (guint64)sp [-1].data.nati;
3437                                 break;
3438                         }
3439                         switch (*ip) {
3440                         case CEE_CONV_OVF_I1_UN:
3441                                 if (value > 127)
3442                                         THROW_EX (mono_get_exception_overflow (), ip);
3443                                 sp [-1].data.i = value;
3444                                 sp [-1].type = VAL_I32;
3445                                 break;
3446                         case CEE_CONV_OVF_I2_UN:
3447                                 if (value > 32767)
3448                                         THROW_EX (mono_get_exception_overflow (), ip);
3449                                 sp [-1].data.i = value;
3450                                 sp [-1].type = VAL_I32;
3451                                 break;
3452 #if SIZEOF_VOID_P == 4
3453                         case CEE_CONV_OVF_I_UN: /* Fall through */
3454 #endif
3455                         case CEE_CONV_OVF_I4_UN:
3456                                 if (value > MYGUINT32_MAX)
3457                                         THROW_EX (mono_get_exception_overflow (), ip);
3458                                 sp [-1].data.i = value;
3459                                 sp [-1].type = VAL_I32;
3460                                 break;
3461                         case CEE_CONV_OVF_U1_UN:
3462                                 if (value > 255)
3463                                         THROW_EX (mono_get_exception_overflow (), ip);
3464                                 sp [-1].data.i = value;
3465                                 sp [-1].type = VAL_I32;
3466                                 break;
3467                         case CEE_CONV_OVF_U2_UN:
3468                                 if (value > 65535)
3469                                         THROW_EX (mono_get_exception_overflow (), ip);
3470                                 sp [-1].data.i = value;
3471                                 sp [-1].type = VAL_I32;
3472                                 break;
3473 #if SIZEOF_VOID_P == 4
3474                         case CEE_CONV_OVF_U_UN: /* Fall through */
3475 #endif
3476                         case CEE_CONV_OVF_U4_UN:
3477                                 if (value > 4294967295U)
3478                                         THROW_EX (mono_get_exception_overflow (), ip);
3479                                 sp [-1].data.i = value;
3480                                 sp [-1].type = VAL_I32;
3481                                 break;
3482                         default:
3483                                 g_assert_not_reached ();
3484                         }
3485                         ++ip;
3486                         BREAK;
3487                 }
3488                 CASE (CEE_BOX) {
3489                         guint32 token;
3490                         MonoClass *class;
3491
3492                         ip++;
3493                         token = read32 (ip);
3494
3495                         if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
3496                                 class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
3497                         else
3498                                 class = mono_class_get (image, token);
3499                         g_assert (class != NULL);
3500
3501                         sp [-1].type = VAL_OBJ;
3502                         if (class->byval_arg.type == MONO_TYPE_VALUETYPE && !class->enumtype) 
3503                                 sp [-1].data.p = mono_value_box (domain, class, sp [-1].data.p);
3504                         else {
3505                                 stackval_to_data (&class->byval_arg, &sp [-1], (char*)&sp [-1], FALSE);
3506                                 sp [-1].data.p = mono_value_box (domain, class, &sp [-1]);
3507                         }
3508                         /* need to vt_free (sp); */
3509
3510                         ip += 4;
3511
3512                         BREAK;
3513                 }
3514                 CASE (CEE_NEWARR) {
3515                         MonoClass *class;
3516                         MonoObject *o;
3517                         guint32 token;
3518
3519                         ip++;
3520                         token = read32 (ip);
3521
3522                         if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
3523                                 class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
3524                         else
3525                                 class = mono_class_get (image, token);
3526
3527                         o = (MonoObject*) mono_array_new (domain, class, sp [-1].data.i);
3528                         ip += 4;
3529
3530                         sp [-1].type = VAL_OBJ;
3531                         sp [-1].data.p = o;
3532                         /*if (profiling_classes) {
3533                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3534                                 count++;
3535                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3536                         }*/
3537
3538                         BREAK;
3539                 }
3540                 CASE (CEE_LDLEN) {
3541                         MonoArray *o;
3542
3543                         ip++;
3544
3545                         g_assert (sp [-1].type == VAL_OBJ);
3546
3547                         o = sp [-1].data.p;
3548                         if (!o)
3549                                 THROW_EX (mono_get_exception_null_reference (), ip - 1);
3550                         
3551                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
3552
3553                         sp [-1].type = VAL_I32;
3554                         sp [-1].data.i = mono_array_length (o);
3555
3556                         BREAK;
3557                 }
3558                 CASE (CEE_LDELEMA) {
3559                         MonoArray *o;
3560                         guint32 esize, token;
3561                         mono_u aindex;
3562                         
3563                         ++ip;
3564                         token = read32 (ip);
3565                         ip += 4;
3566                         sp -= 2;
3567
3568                         g_assert (sp [0].type == VAL_OBJ);
3569                         o = sp [0].data.p;
3570
3571                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
3572                         
3573                         aindex = sp [1].type == VAL_I32? sp [1].data.i: sp [1].data.nati;
3574                         if (aindex >= mono_array_length (o))
3575                                 THROW_EX (mono_get_exception_index_out_of_range (), ip - 5);
3576
3577                         /* check the array element corresponds to token */
3578                         esize = mono_array_element_size (o->obj.vtable->klass);
3579                         
3580                         sp->type = VAL_MP;
3581                         sp->data.p = mono_array_addr_with_size (o, esize, aindex);
3582
3583                         ++sp;
3584                         BREAK;
3585                 }
3586                 CASE (CEE_LDELEM_I1) /* fall through */
3587                 CASE (CEE_LDELEM_U1) /* fall through */
3588                 CASE (CEE_LDELEM_I2) /* fall through */
3589                 CASE (CEE_LDELEM_U2) /* fall through */
3590                 CASE (CEE_LDELEM_I4) /* fall through */
3591                 CASE (CEE_LDELEM_U4) /* fall through */
3592                 CASE (CEE_LDELEM_I8)  /* fall through */
3593                 CASE (CEE_LDELEM_I)  /* fall through */
3594                 CASE (CEE_LDELEM_R4) /* fall through */
3595                 CASE (CEE_LDELEM_R8) /* fall through */
3596                 CASE (CEE_LDELEM_REF) {
3597                         MonoArray *o;
3598                         mono_u aindex;
3599
3600                         sp -= 2;
3601
3602                         g_assert (sp [0].type == VAL_OBJ);
3603                         o = sp [0].data.p;
3604                         if (!o)
3605                                 THROW_EX (mono_get_exception_null_reference (), ip);
3606
3607                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
3608                         
3609                         aindex = sp [1].type == VAL_I32? sp [1].data.i: sp [1].data.nati;
3610                         if (aindex >= mono_array_length (o))
3611                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3612
3613                         /*
3614                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3615                          */
3616                         switch (*ip) {
3617                         case CEE_LDELEM_I1:
3618                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
3619                                 sp [0].type = VAL_I32;
3620                                 break;
3621                         case CEE_LDELEM_U1:
3622                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
3623                                 sp [0].type = VAL_I32;
3624                                 break;
3625                         case CEE_LDELEM_I2:
3626                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
3627                                 sp [0].type = VAL_I32;
3628                                 break;
3629                         case CEE_LDELEM_U2:
3630                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
3631                                 sp [0].type = VAL_I32;
3632                                 break;
3633                         case CEE_LDELEM_I:
3634                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
3635                                 sp [0].type = VAL_NATI;
3636                                 break;
3637                         case CEE_LDELEM_I4:
3638                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
3639                                 sp [0].type = VAL_I32;
3640                                 break;
3641                         case CEE_LDELEM_U4:
3642                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
3643                                 sp [0].type = VAL_I32;
3644                                 break;
3645                         case CEE_LDELEM_I8:
3646                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
3647                                 sp [0].type = VAL_I64;
3648                                 break;
3649                         case CEE_LDELEM_R4:
3650                                 sp [0].data.f = mono_array_get (o, float, aindex);
3651                                 sp [0].type = VAL_DOUBLE;
3652                                 break;
3653                         case CEE_LDELEM_R8:
3654                                 sp [0].data.f = mono_array_get (o, double, aindex);
3655                                 sp [0].type = VAL_DOUBLE;
3656                                 break;
3657                         case CEE_LDELEM_REF:
3658                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
3659                                 sp [0].type = VAL_OBJ;
3660                                 break;
3661                         default:
3662                                 ves_abort();
3663                         }
3664
3665                         ++ip;
3666                         ++sp;
3667                         BREAK;
3668                 }
3669                 CASE (CEE_STELEM_I)  /* fall through */
3670                 CASE (CEE_STELEM_I1) /* fall through */ 
3671                 CASE (CEE_STELEM_I2) /* fall through */
3672                 CASE (CEE_STELEM_I4) /* fall through */
3673                 CASE (CEE_STELEM_I8) /* fall through */
3674                 CASE (CEE_STELEM_R4) /* fall through */
3675                 CASE (CEE_STELEM_R8) /* fall through */
3676                 CASE (CEE_STELEM_REF) {
3677                         MonoArray *o;
3678                         MonoClass *ac;
3679                         mono_u aindex;
3680
3681                         sp -= 3;
3682
3683                         g_assert (sp [0].type == VAL_OBJ);
3684                         o = sp [0].data.p;
3685                         if (!o)
3686                                 THROW_EX (mono_get_exception_null_reference (), ip);
3687
3688                         ac = o->obj.vtable->klass;
3689                         g_assert (MONO_CLASS_IS_ARRAY (ac));
3690                     
3691                         aindex = sp [1].type == VAL_I32? sp [1].data.i: sp [1].data.nati;
3692                         if (aindex >= mono_array_length (o))
3693                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3694
3695                         /*
3696                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3697                          */
3698                         switch (*ip) {
3699                         case CEE_STELEM_I:
3700                                 mono_array_set (o, mono_i, aindex, sp [2].data.nati);
3701                                 break;
3702                         case CEE_STELEM_I1:
3703                                 mono_array_set (o, gint8, aindex, sp [2].data.i);
3704                                 break;
3705                         case CEE_STELEM_I2:
3706                                 mono_array_set (o, gint16, aindex, sp [2].data.i);
3707                                 break;
3708                         case CEE_STELEM_I4:
3709                                 mono_array_set (o, gint32, aindex, sp [2].data.i);
3710                                 break;
3711                         case CEE_STELEM_I8:
3712                                 mono_array_set (o, gint64, aindex, sp [2].data.l);
3713                                 break;
3714                         case CEE_STELEM_R4:
3715                                 mono_array_set (o, float, aindex, sp [2].data.f);
3716                                 break;
3717                         case CEE_STELEM_R8:
3718                                 mono_array_set (o, double, aindex, sp [2].data.f);
3719                                 break;
3720                         case CEE_STELEM_REF:
3721                                 g_assert (sp [2].type == VAL_OBJ);
3722                                 if (sp [2].data.p && !mono_object_isinst (sp [2].data.p, mono_object_class (o)->element_class))
3723                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
3724                                 mono_array_set (o, gpointer, aindex, sp [2].data.p);
3725                                 break;
3726                         default:
3727                                 ves_abort();
3728                         }
3729
3730                         ++ip;
3731                         BREAK;
3732                 }
3733                 CASE (CEE_LDELEM) 
3734                 CASE (CEE_STELEM) 
3735                 CASE (CEE_UNBOX_ANY) 
3736                 CASE (CEE_UNUSED5) 
3737                 CASE (CEE_UNUSED6) 
3738                 CASE (CEE_UNUSED7) 
3739                 CASE (CEE_UNUSED8) 
3740                 CASE (CEE_UNUSED9) 
3741                 CASE (CEE_UNUSED10) 
3742                 CASE (CEE_UNUSED11) 
3743                 CASE (CEE_UNUSED12) 
3744                 CASE (CEE_UNUSED13) 
3745                 CASE (CEE_UNUSED14) 
3746                 CASE (CEE_UNUSED15) 
3747                 CASE (CEE_UNUSED16) 
3748                 CASE (CEE_UNUSED17) ves_abort(); BREAK;
3749
3750 #if SIZEOF_VOID_P == 4
3751                 CASE (CEE_CONV_OVF_I)
3752                 CASE (CEE_CONV_OVF_U) 
3753 #endif
3754                 CASE (CEE_CONV_OVF_I1)
3755                 CASE (CEE_CONV_OVF_I2)
3756                 CASE (CEE_CONV_OVF_I4)
3757                 CASE (CEE_CONV_OVF_U1)
3758                 CASE (CEE_CONV_OVF_U2)
3759                 CASE (CEE_CONV_OVF_U4) {
3760                         gint64 value;
3761                         switch (sp [-1].type) {
3762                         case VAL_DOUBLE:
3763                                 value = (gint64)sp [-1].data.f;
3764                                 break;
3765                         case VAL_I64:
3766                                 value = (gint64)sp [-1].data.l;
3767                                 break;
3768                         case VAL_VALUET:
3769                                 ves_abort();
3770                         case VAL_I32:
3771                                 value = (gint64)sp [-1].data.i;
3772                                 break;
3773                         default:
3774                                 value = (gint64)sp [-1].data.nati;
3775                                 break;
3776                         }
3777                         switch (*ip) {
3778                         case CEE_CONV_OVF_I1:
3779                                 if (value < -128 || value > 127)
3780                                         THROW_EX (mono_get_exception_overflow (), ip);
3781                                 sp [-1].data.i = value;
3782                                 sp [-1].type = VAL_I32;
3783                                 break;
3784                         case CEE_CONV_OVF_I2:
3785                                 if (value < -32768 || value > 32767)
3786                                         THROW_EX (mono_get_exception_overflow (), ip);
3787                                 sp [-1].data.i = value;
3788                                 sp [-1].type = VAL_I32;
3789                                 break;
3790 #if SIZEOF_VOID_P == 4
3791                         case CEE_CONV_OVF_I: /* Fall through */
3792 #endif
3793                         case CEE_CONV_OVF_I4:
3794                                 if (value < MYGINT32_MIN || value > MYGINT32_MAX)
3795                                         THROW_EX (mono_get_exception_overflow (), ip);
3796                                 sp [-1].data.i = value;
3797                                 sp [-1].type = VAL_I32;
3798                                 break;
3799                         case CEE_CONV_OVF_U1:
3800                                 if (value < 0 || value > 255)
3801                                         THROW_EX (mono_get_exception_overflow (), ip);
3802                                 sp [-1].data.i = value;
3803                                 sp [-1].type = VAL_I32;
3804                                 break;
3805                         case CEE_CONV_OVF_U2:
3806                                 if (value < 0 || value > 65535)
3807                                         THROW_EX (mono_get_exception_overflow (), ip);
3808                                 sp [-1].data.i = value;
3809                                 sp [-1].type = VAL_I32;
3810                                 break;
3811 #if SIZEOF_VOID_P == 4
3812                         case CEE_CONV_OVF_U: /* Fall through */
3813 #endif
3814                         case CEE_CONV_OVF_U4:
3815                                 if (value < 0 || value > MYGUINT32_MAX)
3816                                         THROW_EX (mono_get_exception_overflow (), ip);
3817                                 sp [-1].data.i = value;
3818                                 sp [-1].type = VAL_I32;
3819                                 break;
3820                         default:
3821                                 g_assert_not_reached ();
3822                         }
3823                         ++ip;
3824                         BREAK;
3825                 }
3826
3827 #if SIZEOF_VOID_P == 8
3828                 CASE (CEE_CONV_OVF_I)
3829 #endif
3830                 CASE (CEE_CONV_OVF_I8)
3831                         /* FIXME: handle other cases */
3832                         if (sp [-1].type == VAL_I32) {
3833                                 sp [-1].data.l = (guint64)sp [-1].data.i;
3834                                 sp [-1].type = VAL_I64;
3835                         } else if(sp [-1].type == VAL_I64) {
3836                                 /* defined as NOP */
3837                         } else {
3838                                 ves_abort();
3839                         }
3840                         ++ip;
3841                         BREAK;
3842
3843 #if SIZEOF_VOID_P == 8
3844                 CASE (CEE_CONV_OVF_U)
3845 #endif
3846                 CASE (CEE_CONV_OVF_U8)
3847                         /* FIXME: handle other cases */
3848                         if (sp [-1].type == VAL_I32) {
3849                                 sp [-1].data.l = (guint64) sp [-1].data.i;
3850                                 sp [-1].type = VAL_I64;
3851                         } else if(sp [-1].type == VAL_I64) {
3852                                 /* defined as NOP */
3853                         } else {
3854                                 ves_abort();
3855                         }
3856                         ++ip;
3857                         BREAK;
3858                 CASE (CEE_UNUSED50) 
3859                 CASE (CEE_UNUSED18) 
3860                 CASE (CEE_UNUSED19) 
3861                 CASE (CEE_UNUSED20) 
3862                 CASE (CEE_UNUSED21) 
3863                 CASE (CEE_UNUSED22) 
3864                 CASE (CEE_UNUSED23) ves_abort(); BREAK;
3865                 CASE (CEE_REFANYVAL) ves_abort(); BREAK;
3866                 CASE (CEE_CKFINITE)
3867                         if (!finite(sp [-1].data.f))
3868                                 THROW_EX (mono_get_exception_arithmetic (), ip);
3869                         ++ip;
3870                         BREAK;
3871                 CASE (CEE_UNUSED24) ves_abort(); BREAK;
3872                 CASE (CEE_UNUSED25) ves_abort(); BREAK;
3873                 CASE (CEE_MKREFANY) ves_abort(); BREAK;
3874                 CASE (CEE_UNUSED59) 
3875                 CASE (CEE_UNUSED60) 
3876                 CASE (CEE_UNUSED61) 
3877                 CASE (CEE_UNUSED62) 
3878                 CASE (CEE_UNUSED63) 
3879                 CASE (CEE_UNUSED64) 
3880                 CASE (CEE_UNUSED65) 
3881                 CASE (CEE_UNUSED66) 
3882                 CASE (CEE_UNUSED67) ves_abort(); BREAK;
3883                 CASE (CEE_LDTOKEN) {
3884                         gpointer handle;
3885                         MonoClass *handle_class;
3886                         ++ip;
3887                         handle = mono_ldtoken (image, read32 (ip), &handle_class);
3888                         ip += 4;
3889                         vt_alloc (&handle_class->byval_arg, sp, FALSE);
3890                         stackval_from_data (&handle_class->byval_arg, sp, (char*)&handle, FALSE);
3891                         ++sp;
3892                         BREAK;
3893                 }
3894                 CASE (CEE_ADD_OVF)
3895                         --sp;
3896                         /* FIXME: check overflow */
3897                         if (sp->type == VAL_I32) {
3898                                 if (sp [-1].type == VAL_I32) {
3899                                         if (CHECK_ADD_OVERFLOW (sp [-1].data.i, sp [0].data.i))
3900                                                 THROW_EX (mono_get_exception_overflow (), ip);
3901                                         sp [-1].data.i = (gint32)sp [-1].data.i + (gint32)sp [0].data.i;
3902                                 } else {
3903                                         if (CHECK_ADD_OVERFLOW_NAT (sp [-1].data.nati, (mono_i)sp [0].data.i))
3904                                                 THROW_EX (mono_get_exception_overflow (), ip);
3905                                         sp [-1].data.nati = sp [-1].data.nati + (mono_i)sp [0].data.i;
3906                                 }
3907                         } else if (sp->type == VAL_I64) {
3908                                 if (CHECK_ADD_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
3909                                         THROW_EX (mono_get_exception_overflow (), ip);
3910                                 sp [-1].data.l = (gint64)sp [-1].data.l + (gint64)sp [0].data.l;
3911                         } else if (sp->type == VAL_DOUBLE)
3912                                 sp [-1].data.f += sp [0].data.f;
3913                         else {
3914                                 char *p = sp [-1].data.p;
3915                                 p += GET_NATI (sp [0]);
3916                                 sp [-1].data.p = p;
3917                         }
3918                         ++ip;
3919                         BREAK;
3920                 CASE (CEE_ADD_OVF_UN)
3921                         --sp;
3922                         /* FIXME: check overflow, make unsigned */
3923                         if (sp->type == VAL_I32) {
3924                                 if (sp [-1].type == VAL_I32) {
3925                                         if (CHECK_ADD_OVERFLOW_UN (sp [-1].data.i, sp [0].data.i))
3926                                                 THROW_EX (mono_get_exception_overflow (), ip);
3927                                         sp [-1].data.i = (guint32)sp [-1].data.i + (guint32)sp [0].data.i;
3928                                 } else {
3929                                         if (CHECK_ADD_OVERFLOW_NAT_UN (sp [-1].data.nati, (mono_u)sp [0].data.i))
3930                                                 THROW_EX (mono_get_exception_overflow (), ip);
3931                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati + (mono_u)sp [0].data.i;
3932                                 }
3933                         } else if (sp->type == VAL_I64) {
3934                                 if (CHECK_ADD_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
3935                                         THROW_EX (mono_get_exception_overflow (), ip);
3936                                 sp [-1].data.l = (guint64)sp [-1].data.l + (guint64)sp [0].data.l;
3937                         } else if (sp->type == VAL_DOUBLE)
3938                                 sp [-1].data.f += sp [0].data.f;
3939                         else {
3940                                 char *p = sp [-1].data.p;
3941                                 p += GET_NATI (sp [0]);
3942                                 sp [-1].data.p = p;
3943                         }
3944                         ++ip;
3945                         BREAK;
3946                 CASE (CEE_MUL_OVF)
3947                         --sp;
3948                         /* FIXME: check overflow */
3949                         if (sp->type == VAL_I32) {
3950                                 if (sp [-1].type == VAL_NATI) {
3951                                         if (CHECK_MUL_OVERFLOW_NAT (sp [-1].data.nati, sp [0].data.i))
3952                                                 THROW_EX (mono_get_exception_overflow (), ip);
3953                                         sp [-1].data.nati = sp [-1].data.nati * sp [0].data.i;
3954                                         sp [-1].type = VAL_NATI;
3955                                 } else {
3956                                         if (CHECK_MUL_OVERFLOW (sp [-1].data.i, sp [0].data.i))
3957                                                 THROW_EX (mono_get_exception_overflow (), ip);
3958                                         sp [-1].data.i *= sp [0].data.i;
3959                                 }
3960                         }
3961                         else if (sp->type == VAL_I64) {
3962                                 if (CHECK_MUL_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
3963                                         THROW_EX (mono_get_exception_overflow (), ip);
3964                                 sp [-1].data.l *= sp [0].data.l;
3965                         }
3966                         else if (sp->type == VAL_DOUBLE)
3967                                 sp [-1].data.f *= sp [0].data.f;
3968                         else
3969                                 ves_abort();
3970                         ++ip;
3971                         BREAK;
3972                 CASE (CEE_MUL_OVF_UN)
3973                         --sp;
3974                         /* FIXME: check overflow, make unsigned */
3975                         if (sp->type == VAL_I32) {
3976                                 if (sp [-1].type == VAL_NATI) {
3977                                         if (CHECK_MUL_OVERFLOW_NAT_UN (sp [-1].data.nati, (mono_u)sp [0].data.i))
3978                                                 THROW_EX (mono_get_exception_overflow (), ip);
3979                                         sp [-1].data.nati = (mono_u)sp [-1].data.nati * (mono_u)sp [0].data.i;
3980                                         sp [-1].type = VAL_NATI;
3981                                 } else {
3982                                         if (CHECK_MUL_OVERFLOW_UN ((guint32)sp [-1].data.i, (guint32)sp [0].data.i))
3983                                                 THROW_EX (mono_get_exception_overflow (), ip);
3984                                         sp [-1].data.i *= sp [0].data.i;
3985                                 }
3986                         }
3987                         else if (sp->type == VAL_I64) {
3988                                 if (CHECK_MUL_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
3989                                         THROW_EX (mono_get_exception_overflow (), ip);
3990                                 sp [-1].data.l *= sp [0].data.l;
3991                         }
3992                         else if (sp->type == VAL_DOUBLE)
3993                                 sp [-1].data.f *= sp [0].data.f;
3994                         else
3995                                 ves_abort();
3996                         ++ip;
3997                         BREAK;
3998                 CASE (CEE_SUB_OVF)
3999                         --sp;
4000                         /* FIXME: handle undeflow/unsigned */
4001                         /* should probably consider the pointers as unsigned */
4002                         if (sp->type == VAL_I32) {
4003                                 if (sp [-1].type == VAL_I32) {
4004                                         if (CHECK_SUB_OVERFLOW (sp [-1].data.i, sp [0].data.i))
4005                                                 THROW_EX (mono_get_exception_overflow (), ip);
4006                                         sp [-1].data.i -= sp [0].data.i;
4007                                 } else {
4008                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.i;
4009                                         sp [-1].type = VAL_NATI;
4010                                 }
4011                         }
4012                         else if (sp->type == VAL_I64) {
4013                                 if (CHECK_SUB_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
4014                                     THROW_EX (mono_get_exception_overflow (), ip);
4015                                 sp [-1].data.l -= sp [0].data.l;
4016                         }
4017                         else if (sp->type == VAL_DOUBLE)
4018                                 sp [-1].data.f -= sp [0].data.f;
4019                         else {
4020                                 if (sp [-1].type == VAL_I32) {
4021                                         sp [-1].data.nati = sp [-1].data.i - sp [0].data.nati;
4022                                         sp [-1].type = sp [0].type;
4023                                 } else
4024                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.nati;
4025                         }
4026                         ++ip;
4027                         BREAK;
4028                 CASE (CEE_SUB_OVF_UN)
4029                         --sp;
4030                         /* FIXME: handle undeflow/unsigned */
4031                         /* should probably consider the pointers as unsigned */
4032                         if (sp->type == VAL_I32) {
4033                                 if (sp [-1].type == VAL_I32) {
4034                                         if (CHECK_SUB_OVERFLOW_UN (sp [-1].data.i, sp [0].data.i))
4035                                                 THROW_EX (mono_get_exception_overflow (), ip);
4036                                         sp [-1].data.i -= sp [0].data.i;
4037                                 } else {
4038                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.i;
4039                                         sp [-1].type = VAL_NATI;
4040                                 }
4041                         }
4042                         else if (sp->type == VAL_I64) {
4043                                 if (CHECK_SUB_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
4044                                     THROW_EX (mono_get_exception_overflow (), ip);
4045                                 sp [-1].data.l -= sp [0].data.l;
4046                         }
4047                         else if (sp->type == VAL_DOUBLE)
4048                                 sp [-1].data.f -= sp [0].data.f;
4049                         else {
4050                                 if (sp [-1].type == VAL_I32) {
4051                                         sp [-1].data.nati = sp [-1].data.i - sp [0].data.nati;
4052                                         sp [-1].type = sp [0].type;
4053                                 } else
4054                                         sp [-1].data.nati = sp [-1].data.nati - sp [0].data.nati;
4055                         }
4056                         ++ip;
4057                         BREAK;
4058                 CASE (CEE_ENDFINALLY)
4059                         if (finally_ips) {
4060                                 ip = finally_ips->data;
4061                                 finally_ips = g_slist_remove (finally_ips, ip);
4062                                 goto main_loop;
4063                         }
4064                         if (frame->ex)
4065                                 goto handle_fault;
4066                         ves_abort();
4067                         BREAK;
4068                 CASE (CEE_LEAVE) /* Fall through */
4069                 CASE (CEE_LEAVE_S)
4070                         while (sp > frame->stack) {
4071                                 --sp;
4072                                 vt_free (sp);
4073                         }
4074                         frame->ip = ip;
4075                         if (*ip == CEE_LEAVE_S) {
4076                                 ++ip;
4077                                 ip += (signed char) *ip;
4078                                 ++ip;
4079                         } else {
4080                                 ++ip;
4081                                 ip += (gint32) read32 (ip);
4082                                 ip += 4;
4083                         }
4084                         endfinally_ip = ip;
4085                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - header->code)) {
4086                                 frame->ex_handler = NULL;
4087                                 frame->ex = NULL;
4088                         }
4089                         goto handle_finally;
4090                         BREAK;
4091                 CASE (CEE_UNUSED41)
4092                         ++ip;
4093                         switch (*ip) {
4094                         case CEE_MONO_FUNC1: {
4095                                 MonoMarshalConv conv;
4096                                 ++ip;
4097
4098                                 conv = *ip;
4099
4100                                 ++ip;
4101
4102                                 sp--;
4103
4104                                 sp->type = VAL_NATI;
4105
4106                                 switch (conv) {
4107                                 case MONO_MARSHAL_CONV_STR_LPWSTR:
4108                                         sp->data.p = mono_string_to_utf16 (sp->data.p);
4109                                         break;
4110                                 case MONO_MARSHAL_CONV_LPSTR_STR:
4111                                         sp->data.p = mono_string_new_wrapper (sp->data.p);
4112                                         break;
4113                                 case MONO_MARSHAL_CONV_STR_LPTSTR:
4114                                 case MONO_MARSHAL_CONV_STR_LPSTR:
4115                                         sp->data.p = mono_string_to_utf8 (sp->data.p);
4116                                         break;
4117                                 case MONO_MARSHAL_CONV_STR_BSTR:
4118                                         sp->data.p = mono_string_to_bstr (sp->data.p);
4119                                         break;
4120                                 case MONO_MARSHAL_CONV_STR_TBSTR:
4121                                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4122                                         sp->data.p = mono_string_to_ansibstr (sp->data.p);
4123                                         break;
4124                                 case MONO_MARSHAL_CONV_SB_LPSTR:
4125                                         sp->data.p = mono_string_builder_to_utf8 (sp->data.p);
4126                                         break;
4127                                 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
4128                                         sp->data.p = mono_array_to_savearray (sp->data.p);
4129                                         break;
4130                                 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
4131                                         sp->data.p = mono_array_to_lparray (sp->data.p);
4132                                         break;
4133                                 case MONO_MARSHAL_CONV_DEL_FTN:
4134                                         sp->data.p = mono_delegate_to_ftnptr (sp->data.p);
4135                                         break;
4136                                 case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
4137                                         sp->data.p = mono_marshal_string_array (sp->data.p);
4138                                         break;
4139                                 case MONO_MARSHAL_CONV_LPWSTR_STR:
4140                                         sp->data.p = mono_string_from_utf16 (sp->data.p);
4141                                         break;
4142                                 default:
4143                                         fprintf(stderr, "MONO_FUNC1 %d", conv);
4144                                         g_assert_not_reached ();
4145                                 }
4146                                 sp++; 
4147                                 break;
4148                         }
4149                         case CEE_MONO_PROC2: {
4150                                 MonoMarshalConv conv;
4151                                 ++ip;
4152                                 conv = *ip;
4153                                 ++ip;
4154
4155                                 sp -= 2;
4156
4157                                 switch (conv) {
4158                                 case MONO_MARSHAL_CONV_LPSTR_SB:
4159                                         mono_string_utf8_to_builder (sp [0].data.p, sp [1].data.p);
4160                                         break;
4161                                 case MONO_MARSHAL_FREE_ARRAY:
4162                                         mono_marshal_free_array (sp [0].data.p, sp [1].data.i);
4163                                         break;
4164                                 default:
4165                                         g_assert_not_reached ();
4166                                 }                                
4167                                 break;
4168                         }
4169                         case CEE_MONO_PROC3: {
4170                                 MonoMarshalConv conv;
4171                                 ++ip;
4172                                 conv = *ip;
4173                                 ++ip;
4174
4175                                 sp -= 3;
4176
4177                                 switch (conv) {
4178                                 case MONO_MARSHAL_CONV_STR_BYVALSTR:
4179                                         mono_string_to_byvalstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4180                                         break;
4181                                 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
4182                                         mono_string_to_byvalwstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4183                                         break;
4184                                 default:
4185                                         g_assert_not_reached ();
4186                                 }
4187                                 break;
4188                         }
4189                         case CEE_MONO_VTADDR: {
4190                                 ++ip;
4191
4192                                 sp [-1].type = VAL_MP;
4193                                 /* do nothing? */
4194                                 break;
4195                         }
4196                         case CEE_MONO_LDPTR: {
4197                                 guint32 token;
4198                                 ++ip;
4199                                 
4200                                 token = read32 (ip);
4201                                 ip += 4;
4202                                 
4203                                 sp->type = VAL_NATI;
4204                                 sp->data.p = mono_method_get_wrapper_data (frame->method, token);
4205                                 ++sp;
4206                                 break;
4207                         }
4208                         case CEE_MONO_FREE: {
4209                                 ++ip;
4210
4211                                 sp -= 1;
4212                                 g_free (sp->data.p);
4213                                 break;
4214                         }
4215                         case CEE_MONO_OBJADDR: {
4216                                 ++ip;
4217
4218                                 sp->type = VAL_MP;
4219                                 /* do nothing? */
4220                                 break;
4221                         }
4222                         case CEE_MONO_NEWOBJ: {
4223                                 MonoClass *class;
4224                                 guint32 token;
4225
4226                                 ++ip;
4227                                 token = read32 (ip);
4228                                 ip += 4;
4229
4230                                 class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
4231                                 sp->data.p = mono_object_new (domain, class);
4232                                 sp++;
4233                                 break;
4234                         }
4235                         case CEE_MONO_RETOBJ: {
4236                                 MonoClass *class;
4237                                 guint32 token;
4238
4239                                 ++ip;
4240                                 token = read32 (ip);
4241                                 ip += 4;
4242
4243                                 sp--;
4244
4245                                 class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
4246                                 
4247                                 stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);
4248
4249                                 if (sp > frame->stack)
4250                                         g_warning ("more values on stack: %d", sp-frame->stack);
4251                                 goto exit_frame;
4252                         }
4253                         case CEE_MONO_LDNATIVEOBJ: {
4254                                 MonoClass *class;
4255                                 guint32 token;
4256
4257                                 ++ip;
4258                                 token = read32 (ip);
4259                                 ip += 4;
4260
4261                                 class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
4262                                 g_assert(class->valuetype);
4263
4264                                 sp [-1].type = VAL_MP;
4265
4266                                 break;
4267                         }
4268                         default:
4269                                 g_error ("Unimplemented opcode: 0xF0 %02x at 0x%x\n", *ip, ip-header->code);
4270                         }
4271                         BREAK;
4272                 CASE (CEE_UNUSED26) 
4273                 CASE (CEE_UNUSED27) 
4274                 CASE (CEE_UNUSED28) 
4275                 CASE (CEE_UNUSED29) 
4276                 CASE (CEE_UNUSED30) 
4277                 CASE (CEE_UNUSED31) 
4278                 CASE (CEE_UNUSED32) 
4279                 CASE (CEE_UNUSED33) 
4280                 CASE (CEE_UNUSED34) 
4281                 CASE (CEE_UNUSED35) 
4282                 CASE (CEE_UNUSED36) 
4283                 CASE (CEE_UNUSED37) 
4284                 CASE (CEE_UNUSED38) 
4285                 CASE (CEE_UNUSED39) 
4286                 CASE (CEE_UNUSED40) 
4287                 CASE (CEE_UNUSED42) 
4288                 CASE (CEE_UNUSED43) 
4289                 CASE (CEE_UNUSED44) 
4290                 CASE (CEE_UNUSED45) 
4291                 CASE (CEE_UNUSED46) 
4292                 CASE (CEE_UNUSED47) 
4293                 CASE (CEE_UNUSED48)
4294                 CASE (CEE_PREFIX7)
4295                 CASE (CEE_PREFIX6)
4296                 CASE (CEE_PREFIX5)
4297                 CASE (CEE_PREFIX4)
4298                 CASE (CEE_PREFIX3)
4299                 CASE (CEE_PREFIX2)
4300                 CASE (CEE_PREFIXREF) ves_abort(); BREAK;
4301                 /*
4302                  * Note: Exceptions thrown when executing a prefixed opcode need
4303                  * to take into account the number of prefix bytes (usually the
4304                  * throw point is just (ip - n_prefix_bytes).
4305                  */
4306                 SUB_SWITCH
4307                         ++ip;
4308                         switch (*ip) {
4309                         case CEE_ARGLIST: ves_abort(); break;
4310                         case CEE_CEQ: {
4311                                 gint32 result;
4312                                 ++ip;
4313                                 sp -= 2;
4314
4315                                 if (sp->type == VAL_I32)
4316                                         result = (mono_i)sp [0].data.i == (mono_i)GET_NATI (sp [1]);
4317                                 else if (sp->type == VAL_I64)
4318                                         result = sp [0].data.l == sp [1].data.l;
4319                                 else if (sp->type == VAL_DOUBLE) {
4320                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
4321                                                 result = 0;
4322                                         else
4323                                                 result = sp [0].data.f == sp [1].data.f;
4324                                 } else
4325                                         result = sp [0].data.nati == GET_NATI (sp [1]);
4326                                 sp->type = VAL_I32;
4327                                 sp->data.i = result;
4328
4329                                 sp++;
4330                                 break;
4331                         }
4332                         case CEE_CGT: {
4333                                 gint32 result;
4334                                 ++ip;
4335                                 sp -= 2;
4336
4337                                 if (sp->type == VAL_I32)
4338                                         result = (mono_i)sp [0].data.i > (mono_i)GET_NATI (sp [1]);
4339                                 else if (sp->type == VAL_I64)
4340                                         result = sp [0].data.l > sp [1].data.l;
4341                                 else if (sp->type == VAL_DOUBLE) {
4342                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
4343                                                 result = 0;
4344                                         else
4345                                                 result = sp [0].data.f > sp [1].data.f;
4346                                 } else
4347                                         result = (mono_i)sp [0].data.nati > (mono_i)GET_NATI (sp [1]);
4348                                 sp->type = VAL_I32;
4349                                 sp->data.i = result;
4350
4351                                 sp++;
4352                                 break;
4353                         }
4354                         case CEE_CGT_UN: {
4355                                 gint32 result;
4356                                 ++ip;
4357                                 sp -= 2;
4358
4359                                 if (sp->type == VAL_I32)
4360                                         result = (mono_u)sp [0].data.i > (mono_u)GET_NATI (sp [1]);
4361                                 else if (sp->type == VAL_I64)
4362                                         result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
4363                                 else if (sp->type == VAL_DOUBLE)
4364                                         result = isnan (sp [0].data.f) || isnan (sp [1].data.f) ||
4365                                                 sp[0].data.f > sp[1].data.f;
4366                                 else
4367                                         result = (mono_u)sp [0].data.nati > (mono_u)GET_NATI (sp [1]);
4368                                 sp->type = VAL_I32;
4369                                 sp->data.i = result;
4370
4371                                 sp++;
4372                                 break;
4373                         }
4374                         case CEE_CLT: {
4375                                 gint32 result;
4376                                 ++ip;
4377                                 sp -= 2;
4378
4379                                 if (sp->type == VAL_I32)
4380                                         result = (mono_i)sp [0].data.i < (mono_i)GET_NATI (sp [1]);
4381                                 else if (sp->type == VAL_I64)
4382                                         result = sp [0].data.l < sp [1].data.l;
4383                                 else if (sp->type == VAL_DOUBLE) {
4384                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
4385                                                 result = 0;
4386                                         else
4387                                                 result = sp [0].data.f < sp [1].data.f;
4388                                 } else
4389                                         result = (mono_i)sp [0].data.nati < (mono_i)GET_NATI (sp [1]);
4390                                 sp->type = VAL_I32;
4391                                 sp->data.i = result;
4392
4393                                 sp++;
4394                                 break;
4395                         }
4396                         case CEE_CLT_UN: {
4397                                 gint32 result;
4398                                 ++ip;
4399                                 sp -= 2;
4400
4401                                 if (sp->type == VAL_I32)
4402                                         result = (mono_u)sp [0].data.i < (mono_u)GET_NATI (sp [1]);
4403                                 else if (sp->type == VAL_I64)
4404                                         result = (guint64)sp [0].data.l < (guint64)sp [1].data.l;
4405                                 else if (sp->type == VAL_DOUBLE)
4406                                         result = isnan (sp [0].data.f) || isnan (sp [1].data.f) ||
4407                                                 sp[0].data.f < sp[1].data.f;
4408                                 else
4409                                         result = (mono_u)sp [0].data.nati < (mono_u)GET_NATI (sp [1]);
4410                                 sp->type = VAL_I32;
4411                                 sp->data.i = result;
4412
4413                                 sp++;
4414                                 break;
4415                         }
4416                         case CEE_LDFTN:
4417                         case CEE_LDVIRTFTN: {
4418                                 int virtual = *ip == CEE_LDVIRTFTN;
4419                                 MonoMethod *m;
4420                                 guint32 token;
4421                                 ++ip;
4422                                 token = read32 (ip);
4423                                 ip += 4;
4424
4425                                 if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
4426                                         m = (MonoMethod *)mono_method_get_wrapper_data (frame->method, token);
4427                                 else 
4428                                         m = mono_get_method (image, token, NULL);
4429
4430                                 if (!m)
4431                                         THROW_EX (mono_get_exception_missing_method (), ip - 5);
4432                                 if (virtual) {
4433                                         --sp;
4434                                         if (!sp->data.p)
4435                                                 THROW_EX (mono_get_exception_null_reference (), ip - 5);
4436                                         
4437                                         m = get_virtual_method (domain, m, sp);
4438                                 }
4439
4440                                 /* 
4441                                  * This prevents infinite cycles since the wrapper contains
4442                                  * an ldftn too.
4443                                  */
4444                                 if (frame->method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED)
4445                                         if (m && m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
4446                                                 m = mono_marshal_get_synchronized_wrapper (m);
4447
4448                                 sp->type = VAL_NATI;
4449                                 sp->data.p = mono_create_method_pointer (m);
4450                                 ++sp;
4451                                 break;
4452                         }
4453                         case CEE_UNUSED56: ves_abort(); break;
4454                         case CEE_LDARG: {
4455                                 guint32 arg_pos;
4456                                 ++ip;
4457                                 arg_pos = read16 (ip);
4458                                 ip += 2;
4459                                 vt_alloc (ARG_TYPE (signature, arg_pos), sp, signature->pinvoke);
4460                                 stackval_from_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos), signature->pinvoke);
4461                                 ++sp;
4462                                 break;
4463                         }
4464                         case CEE_LDARGA: {
4465                                 guint32 anum;
4466                                 ++ip;
4467                                 anum = read16 (ip);
4468                                 ip += 2;
4469                                 sp->data.vt = ARG_POS (anum);
4470                                 sp->type = VAL_MP;
4471                                 ++sp;
4472                                 break;
4473                         }
4474                         case CEE_STARG: {
4475                                 guint32 arg_pos;
4476                                 ++ip;
4477                                 arg_pos = read16 (ip);
4478                                 ip += 2;
4479                                 --sp;
4480                                 stackval_to_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos), signature->pinvoke);
4481                                 vt_free (sp);
4482                                 break;
4483                         }
4484                         case CEE_LDLOC: {
4485                                 guint32 loc_pos;
4486                                 ++ip;
4487                                 loc_pos = read16 (ip);
4488                                 ip += 2;
4489                                 vt_alloc (LOCAL_TYPE (header, loc_pos), sp, FALSE);
4490                                 stackval_from_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos), FALSE);
4491                                 ++sp;
4492                                 break;
4493                         }
4494                         case CEE_LDLOCA: {
4495                                 MonoType *t;
4496                                 guint32 loc_pos;
4497
4498                                 ++ip;
4499                                 loc_pos = read16 (ip);
4500                                 ip += 2;
4501                                 t = LOCAL_TYPE (header, loc_pos);
4502                                 sp->data.vt = LOCAL_POS (loc_pos);
4503
4504                                 sp->type = VAL_MP;
4505
4506                                 ++sp;
4507                                 break;
4508                         }
4509                         case CEE_STLOC: {
4510                                 guint32 loc_pos;
4511                                 ++ip;
4512                                 loc_pos = read16 (ip);
4513                                 ip += 2;
4514                                 --sp;
4515                                 stackval_to_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos), FALSE);
4516                                 vt_free (sp);
4517                                 break;
4518                         }
4519                         case CEE_LOCALLOC:
4520                                 --sp;
4521                                 if (sp != frame->stack)
4522                                         THROW_EX (mono_get_exception_execution_engine (NULL), ip - 1);
4523                                 ++ip;
4524                                 sp->data.p = alloca (sp->data.i);
4525                                 sp->type = VAL_MP;
4526                                 sp++;
4527                                 break;
4528                         case CEE_UNUSED57: ves_abort(); break;
4529                         case CEE_ENDFILTER: ves_abort(); break;
4530                         case CEE_UNALIGNED_:
4531                                 ++ip;
4532                                 unaligned_address = 1;
4533                                 break;
4534                         case CEE_VOLATILE_:
4535                                 ++ip;
4536                                 volatile_address = 1;
4537                                 break;
4538                         case CEE_TAIL_:
4539                                 ++ip;
4540                                 tail_recursion = 1;
4541                                 break;
4542                         case CEE_INITOBJ: {
4543                                 guint32 token;
4544                                 MonoClass *class;
4545
4546                                 ++ip;
4547                                 token = read32 (ip);
4548                                 ip += 4;
4549
4550                                 class = mono_class_get (image, token);
4551
4552                                 --sp;
4553                                 g_assert (sp->type == VAL_TP || sp->type == VAL_MP);
4554                                 memset (sp->data.vt, 0, mono_class_value_size (class, NULL));
4555                                 break;
4556                         }
4557                         case CEE_CONSTRAINED_: {
4558                                 guint32 token;
4559                                 /* FIXME: implement */
4560                                 ++ip;
4561                                 token = read32 (ip);
4562                                 ip += 4;
4563                                 break;
4564                         }
4565                         case CEE_CPBLK:
4566                                 sp -= 3;
4567                                 if (!sp [0].data.p || !sp [1].data.p)
4568                                         THROW_EX (mono_get_exception_null_reference(), ip - 1);
4569                                 ++ip;
4570                                 /* FIXME: value and size may be int64... */
4571                                 memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4572                                 break;
4573                         case CEE_INITBLK:
4574                                 sp -= 3;
4575                                 if (!sp [0].data.p)
4576                                         THROW_EX (mono_get_exception_null_reference(), ip - 1);
4577                                 ++ip;
4578                                 /* FIXME: value and size may be int64... */
4579                                 memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
4580                                 break;
4581                         case CEE_NO_:
4582                                 /* FIXME: implement */
4583                                 ip += 2;
4584                                 break;
4585                         case CEE_RETHROW:
4586                                 /* 
4587                                  * need to clarify what this should actually do:
4588                                  * start the search from the last found handler in
4589                                  * this method or continue in the caller or what.
4590                                  * Also, do we need to run finally/fault handlers after a retrow?
4591                                  * Well, this implementation will follow the usual search
4592                                  * for an handler, considering the current ip as throw spot.
4593                                  * We need to NULL frame->ex_handler for the later code to
4594                                  * actually run the new found handler.
4595                                  */
4596                                 frame->ex_handler = NULL;
4597                                 THROW_EX (frame->ex, ip - 1);
4598                                 break;
4599                         case CEE_UNUSED: ves_abort(); break;
4600                         case CEE_SIZEOF: {
4601                                 guint32 token;
4602                                 int align;
4603                                 ++ip;
4604                                 token = read32 (ip);
4605                                 ip += 4;
4606                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
4607                                         MonoType *type = mono_type_create_from_typespec (image, token);
4608                                         sp->data.i = mono_type_size (type, &align);
4609                                         mono_metadata_free_type (type);
4610                                 } else {
4611                                         MonoClass *szclass = mono_class_get (image, token);
4612                                         mono_class_init (szclass);
4613                                         if (!szclass->valuetype)
4614                                                 THROW_EX (mono_exception_from_name (mono_defaults.corlib, "System", "InvalidProgramException"), ip - 5);
4615                                         sp->data.i = mono_class_value_size (szclass, &align);
4616                                 }
4617                                 sp->type = VAL_I32;
4618                                 ++sp;
4619                                 break;
4620                         }
4621                         case CEE_REFANYTYPE: ves_abort(); break;
4622                         default:
4623                                 g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-header->code);
4624                         }
4625                         continue;
4626                 DEFAULT;
4627                 }
4628         }
4629
4630         g_assert_not_reached ();
4631         /*
4632          * Exception handling code.
4633          * The exception object is stored in frame->ex.
4634          */
4635
4636         handle_exception:
4637         {
4638                 int i;
4639                 guint32 ip_offset;
4640                 MonoInvocation *inv;
4641                 MonoMethodHeader *hd;
4642                 MonoExceptionClause *clause;
4643                 /*char *message;*/
4644                 MonoObject *ex_obj;
4645
4646 #if DEBUG_INTERP
4647                 if (tracing)
4648                         g_print ("* Handling exception '%s' at IL_%04x\n", frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, frame->ip - header->code);
4649 #endif
4650                 if (die_on_exception)
4651                         goto die_on_ex;
4652
4653                 if (frame->ex == quit_exception)
4654                         goto handle_finally;
4655                 
4656                 for (inv = frame; inv; inv = inv->parent) {
4657                         if (inv->method == NULL)
4658                                 continue;
4659                         if (inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
4660                                 continue;
4661                         if (inv->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
4662                                 continue;
4663                         hd = ((MonoMethodNormal*)inv->method)->header;
4664                         ip_offset = inv->ip - hd->code;
4665                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
4666                         for (i = 0; i < hd->num_clauses; ++i) {
4667                                 clause = &hd->clauses [i];
4668                                 if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4669                                         if (!clause->flags) {
4670                                                 if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (inv->method->klass->image, clause->token_or_filter))) {
4671                                                         /* 
4672                                                          * OK, we found an handler, now we need to execute the finally
4673                                                          * and fault blocks before branching to the handler code.
4674                                                          */
4675                                                         inv->ex_handler = clause;
4676 #if DEBUG_INTERP
4677                                                         if (tracing)
4678                                                                 g_print ("* Found handler at '%s'\n", inv->method->name);
4679 #endif
4680                                                         goto handle_finally;
4681                                                 }
4682                                         } else {
4683                                                 /* FIXME: handle filter clauses */
4684                                                 g_assert (0);
4685                                         }
4686                                 }
4687                         }
4688                 }
4689                 /*
4690                  * If we get here, no handler was found: print a stack trace.
4691                  */
4692                 for (inv = frame; inv; inv = inv->parent) {
4693                         if (inv->invoke_trap)
4694                                 goto handle_finally;
4695                 }
4696 die_on_ex:
4697                 ex_obj = (MonoObject*)frame->ex;
4698                 mono_unhandled_exception (ex_obj);
4699                 exit (1);
4700         }
4701         handle_finally:
4702         {
4703                 int i;
4704                 guint32 ip_offset;
4705                 MonoExceptionClause *clause;
4706                 GSList *old_list = finally_ips;
4707                 
4708 #if DEBUG_INTERP
4709                 if (tracing)
4710                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - header->code);
4711 #endif
4712                 if ((frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
4713                                 || (frame->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
4714                         goto exit_frame;
4715                 }
4716                 ip_offset = frame->ip - header->code;
4717
4718                 if (endfinally_ip != NULL)
4719                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
4720                 for (i = 0; i < header->num_clauses; ++i)
4721                         if (frame->ex_handler == &header->clauses [i])
4722                                 break;
4723                 while (i > 0) {
4724                         --i;
4725                         clause = &header->clauses [i];
4726                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - header->code)))) {
4727                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
4728                                         ip = header->code + clause->handler_offset;
4729                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
4730 #if DEBUG_INTERP
4731                                         if (tracing)
4732                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
4733 #endif
4734                                 }
4735                         }
4736                 }
4737
4738                 endfinally_ip = NULL;
4739
4740                 if (old_list != finally_ips && finally_ips) {
4741                         ip = finally_ips->data;
4742                         finally_ips = g_slist_remove (finally_ips, ip);
4743                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
4744                         goto main_loop;
4745                 }
4746
4747                 /*
4748                  * If an exception is set, we need to execute the fault handler, too,
4749                  * otherwise, we continue normally.
4750                  */
4751                 if (frame->ex)
4752                         goto handle_fault;
4753                 ves_abort();
4754         }
4755         handle_fault:
4756         {
4757                 int i;
4758                 guint32 ip_offset;
4759                 MonoExceptionClause *clause;
4760                 
4761 #if DEBUG_INTERP
4762                 if (tracing)
4763                         g_print ("* Handle fault\n");
4764 #endif
4765                 ip_offset = frame->ip - header->code;
4766                 for (i = 0; i < header->num_clauses; ++i) {
4767                         clause = &header->clauses [i];
4768                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4769                                 ip = header->code + clause->handler_offset;
4770 #if DEBUG_INTERP
4771                                 if (tracing)
4772                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
4773 #endif
4774                                 goto main_loop;
4775                         }
4776                 }
4777                 /*
4778                  * If the handler for the exception was found in this method, we jump
4779                  * to it right away, otherwise we return and let the caller run
4780                  * the finally, fault and catch blocks.
4781                  * This same code should be present in the endfault opcode, but it
4782                  * is corrently not assigned in the ECMA specs: LAMESPEC.
4783                  */
4784                 if (frame->ex_handler) {
4785 #if DEBUG_INTERP
4786                         if (tracing)
4787                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
4788 #endif
4789                         ip = header->code + frame->ex_handler->handler_offset;
4790                         sp = frame->stack;
4791                         sp->type = VAL_OBJ;
4792                         sp->data.p = frame->ex;
4793                         ++sp;
4794                         goto main_loop;
4795                 }
4796                 goto exit_frame;
4797         }
4798 exit_frame:
4799         DEBUG_LEAVE ();
4800 }
4801
4802 void
4803 ves_exec_method (MonoInvocation *frame)
4804 {
4805         ThreadContext *context = TlsGetValue (thread_context_id);
4806         ThreadContext context_struct;
4807         if (context == NULL) {
4808                 context = &context_struct;
4809                 context_struct.base_frame = frame;
4810                 context_struct.current_frame = NULL;
4811                 context_struct.current_env = NULL;
4812                 context_struct.search_for_handler = 0;
4813                 TlsSetValue (thread_context_id, context);
4814         }
4815         frame->ip = NULL;
4816         frame->parent = context->current_frame;
4817         ves_exec_method_with_context(frame, context);
4818         if (frame->ex) {
4819                 if (context->current_env) {
4820                         context->env_frame->ex = frame->ex;
4821                         longjmp (*context->current_env, 1);
4822                 }
4823                 else
4824                         mono_unhandled_exception ((MonoObject*)frame->ex);
4825         }
4826         if (context->base_frame == frame)
4827                 TlsSetValue (thread_context_id, NULL);
4828         else
4829                 context->current_frame = frame->parent;
4830 }
4831
4832 static int 
4833 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4834 {
4835         MonoImage *image = assembly->image;
4836         MonoCLIImageInfo *iinfo;
4837         MonoMethod *method;
4838         MonoObject *exc = NULL;
4839         int rval;
4840
4841         iinfo = image->image_info;
4842         method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
4843         if (!method)
4844                 g_error ("No entry point method found in %s", image->name);
4845
4846         rval = mono_runtime_run_main (method, argc, argv, &exc);
4847         if (exc != NULL)
4848                 mono_unhandled_exception (exc);
4849
4850         return rval;
4851 }
4852
4853 static void
4854 usage (void)
4855 {
4856         fprintf (stderr,
4857                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4858                  "Usage is: mint [options] executable args...\n\n", VERSION);
4859         fprintf (stderr,
4860                  "Runtime Debugging:\n"
4861 #ifdef DEBUG_INTERP
4862                  "   --debug\n"
4863 #endif
4864                  "   --dieonex\n"
4865                  "   --noptr\t\t\tdon't print pointer addresses in trace output\n"
4866                  "   --opcode-count\n"
4867                  "   --print-vtable\n"
4868                  "   --traceclassinit\n"
4869                  "\n"
4870                  "Development:\n"
4871                  "   --debug method_name\n"
4872                  "   --profile\n"
4873                  "   --trace\n"
4874                  "   --traceops\n"
4875                  "\n"
4876                  "Runtime:\n"
4877                  "   --config filename  load the specified config file instead of the default\n"
4878                  "   --workers n        maximum number of worker threads\n"
4879                 );
4880         exit (1);
4881 }
4882
4883 #ifdef RUN_TEST
4884 static void
4885 test_load_class (MonoImage* image)
4886 {
4887         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
4888         MonoClass *klass;
4889         int i;
4890
4891         for (i = 1; i <= t->rows; ++i) {
4892                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
4893                 mono_class_init (klass);
4894         }
4895 }
4896 #endif
4897
4898 static MonoException * segv_exception = NULL;
4899
4900 static void
4901 segv_handler (int signum)
4902 {
4903         signal (signum, segv_handler);
4904         mono_raise_exception (segv_exception);
4905 }
4906
4907
4908 static void
4909 quit_handler (int signum)
4910 {
4911         signal (signum, quit_handler);
4912         mono_raise_exception (quit_exception);
4913 }
4914
4915 static MonoBoolean
4916 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
4917                           MonoReflectionMethod **method, 
4918                           gint32 *iloffset, gint32 *native_offset,
4919                           MonoString **file, gint32 *line, gint32 *column)
4920 {
4921         if (iloffset)
4922                 *iloffset = 0;
4923         if (native_offset)
4924                 *native_offset = 0;
4925         if (method)
4926                 *method = NULL;
4927         if (line)
4928                 *line = 0;
4929         if (column)
4930                 *column = 0;
4931         if (file)
4932                 *file = mono_string_new (mono_domain_get (), "unknown");
4933
4934         return TRUE;
4935 }
4936
4937 static MonoArray *
4938 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
4939 {
4940         return NULL;
4941 }
4942
4943 typedef struct
4944 {
4945         MonoDomain *domain;
4946         int enable_debugging;
4947         char *file;
4948         int argc;
4949         char **argv;
4950 } MainThreadArgs;
4951
4952 static void main_thread_handler (gpointer user_data)
4953 {
4954         MainThreadArgs *main_args=(MainThreadArgs *)user_data;
4955         MonoAssembly *assembly;
4956         char *error;
4957
4958         if (main_args->enable_debugging)
4959                 mono_debug_init (main_args->domain, MONO_DEBUG_FORMAT_MONO);
4960
4961         assembly = mono_domain_assembly_open (main_args->domain,
4962                                               main_args->file);
4963
4964         if (!assembly){
4965                 fprintf (stderr, "Can not open image %s\n", main_args->file);
4966                 exit (1);
4967         }
4968
4969         if (main_args->enable_debugging)
4970                 mono_debug_init_2 (assembly);
4971
4972 #ifdef RUN_TEST
4973         test_load_class (assembly->image);
4974 #else
4975         error = mono_verify_corlib ();
4976         if (error) {
4977                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
4978                 exit (1);
4979         }
4980         segv_exception = mono_get_exception_null_reference ();
4981         segv_exception->message = mono_string_new (main_args->domain, "Segmentation fault");
4982         signal (SIGSEGV, segv_handler);
4983         /* perhaps we should use a different class for this exception... */
4984         quit_exception = mono_get_exception_null_reference ();
4985         quit_exception->message = mono_string_new (main_args->domain, "Quit");
4986         signal (SIGINT, quit_handler);
4987
4988         ves_exec (main_args->domain, assembly, main_args->argc, main_args->argv);
4989 #endif
4990 }
4991
4992 static void
4993 mono_runtime_install_handlers (void)
4994 {
4995         /* FIXME: anything to do here? */
4996 }
4997
4998 static void
4999 quit_function (MonoDomain *domain, gpointer user_data)
5000 {
5001         mono_profiler_shutdown ();
5002         
5003         mono_runtime_cleanup (domain);
5004         mono_domain_unload (domain, TRUE);
5005
5006 }
5007
5008 int 
5009 main (int argc, char *argv [])
5010 {
5011         MonoDomain *domain;
5012         int retval = 0, i, ocount = 0;
5013         char *file, *config_file = NULL;
5014         int enable_debugging = FALSE;
5015         MainThreadArgs main_args;
5016         
5017         if (argc < 2)
5018                 usage ();
5019
5020         for (i = 1; i < argc && argv [i][0] == '-'; i++){
5021                 if (strcmp (argv [i], "--trace") == 0)
5022                         global_tracing = 1;
5023                 if (strcmp (argv [i], "--noptr") == 0)
5024                         global_no_pointers = 1;
5025                 if (strcmp (argv [i], "--traceops") == 0)
5026                         global_tracing = 2;
5027                 if (strcmp (argv [i], "--dieonex") == 0) {
5028                         die_on_exception = 1;
5029                         enable_debugging = 1;
5030                 }
5031                 if (strcmp (argv [i], "--print-vtable") == 0)
5032                         mono_print_vtable = TRUE;
5033                 if (strcmp (argv [i], "--profile") == 0)
5034                         mono_profiler_load (NULL);
5035                 if (strcmp (argv [i], "--opcode-count") == 0)
5036                         ocount = 1;
5037                 if (strcmp (argv [i], "--config") == 0)
5038                         config_file = argv [++i];
5039                 if (strcmp (argv [i], "--workers") == 0) {
5040                         mono_max_worker_threads = atoi (argv [++i]);
5041                         if (mono_max_worker_threads < 1)
5042                                 mono_max_worker_threads = 1;
5043                 }
5044                 if (strcmp (argv [i], "--help") == 0)
5045                         usage ();
5046 #if DEBUG_INTERP
5047                 if (strcmp (argv [i], "--debug") == 0) {
5048                         MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
5049                         if (!desc)
5050                                 g_error ("Invalid method name '%s'", argv [i]);
5051                         db_methods = g_list_append (db_methods, desc);
5052                 }
5053 #endif
5054         }
5055         
5056         file = argv [i];
5057
5058         if (!file)
5059                 usage ();
5060
5061         g_set_prgname (file);
5062         mono_set_rootdir ();
5063         
5064         g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
5065         g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
5066
5067         g_thread_init (NULL);
5068
5069         thread_context_id = TlsAlloc ();
5070         TlsSetValue (thread_context_id, NULL);
5071         InitializeCriticalSection(&calc_section);
5072
5073         mono_install_compile_method (mono_create_method_pointer);
5074         mono_install_runtime_invoke (interp_mono_runtime_invoke);
5075         mono_install_remoting_trampoline (interp_create_remoting_trampoline);
5076
5077         mono_install_handler (interp_ex_handler);
5078         mono_install_stack_walk (interp_walk_stack);
5079         mono_runtime_install_cleanup (quit_function);
5080
5081         domain = mono_init (file);
5082 #ifdef __hpux /* generates very big stack frames */
5083         mono_threads_set_default_stacksize(32*1024*1024);
5084 #endif
5085         mono_config_parse (config_file);
5086         mono_init_icall ();
5087         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", ves_icall_get_frame_info);
5088         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", ves_icall_get_trace);
5089         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
5090
5091         mono_runtime_init (domain, NULL, NULL);
5092
5093         main_args.domain=domain;
5094         main_args.file=file;
5095         main_args.argc=argc-i;
5096         main_args.argv=argv+i;
5097         main_args.enable_debugging=enable_debugging;
5098         
5099         mono_runtime_exec_managed_code (domain, main_thread_handler,
5100                                         &main_args);
5101
5102         quit_function (domain, NULL);
5103
5104         /* Get the return value from System.Environment.ExitCode */
5105         retval=mono_environment_exitcode_get ();
5106
5107 #if DEBUG_INTERP
5108         if (ocount) {
5109                 fprintf (stderr, "opcode count: %ld\n", opcode_count);
5110                 fprintf (stderr, "fcall count: %ld\n", fcall_count);
5111         }
5112 #endif
5113         return retval;
5114 }