2002-05-16 Radek Doulik <rodo@ximian.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 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
25 #if HAVE_BOEHM_GC
26 #include <gc/gc.h>
27 #endif
28
29 #ifdef HAVE_ALLOCA_H
30 #   include <alloca.h>
31 #else
32 #   ifdef __CYGWIN__
33 #      define alloca __builtin_alloca
34 #   endif
35 #endif
36
37 /* trim excessive headers */
38 #include <mono/metadata/image.h>
39 #include <mono/metadata/assembly.h>
40 #include <mono/metadata/cil-coff.h>
41 #include <mono/metadata/mono-endian.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/blob.h>
44 #include <mono/metadata/tokentype.h>
45 #include <mono/metadata/loader.h>
46 #include <mono/metadata/threads.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/cli/types.h>*/
57 #include "interp.h"
58 #include "hacks.h"
59
60 #ifdef _WIN32
61 #define isnan _isnan
62 #define finite _finite
63 #endif
64
65 /* If true, then we output the opcodes as we interpret them */
66 static int global_tracing = 0;
67 static int global_no_pointers = 0;
68
69 static int debug_indent_level = 0;
70
71 /*
72  * Pull the list of opcodes
73  */
74 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
75         a = i,
76
77 enum {
78 #include "mono/cil/opcode.def"
79         LAST = 0xff
80 };
81 #undef OPDEF
82
83 #define GET_NATI(sp) ((sp).data.nati)
84 #define CSIZE(x) (sizeof (x) / 4)
85
86 #define INIT_FRAME(frame,parent_frame,obj_this,method_args,method_retval,mono_method)   \
87         do {    \
88                 (frame)->parent = (parent_frame);       \
89                 (frame)->obj = (obj_this);      \
90                 (frame)->stack_args = (method_args);    \
91                 (frame)->retval = (method_retval);      \
92                 (frame)->method = (mono_method);        \
93                 (frame)->ex_handler = NULL;     \
94                 (frame)->ex = NULL;     \
95                 (frame)->child = NULL;  \
96         } while (0)
97
98 void ves_exec_method (MonoInvocation *frame);
99
100 typedef void (*ICallMethod) (MonoInvocation *frame);
101
102 static guint32 die_on_exception = 0;
103 static guint32 frame_thread_id = 0;
104
105 #define DEBUG_INTERP 1
106 #if DEBUG_INTERP
107
108 static unsigned long opcode_count = 0;
109 static unsigned long fcall_count = 0;
110 static int break_on_method = 0;
111 static GList *db_methods = NULL;
112
113 static void
114 output_indent (void)
115 {
116         int h;
117
118         for (h = 0; h < debug_indent_level; h++)
119                 g_print ("  ");
120 }
121
122 static void
123 db_match_method (gpointer data, gpointer user_data)
124 {
125         MonoMethod *m = (MonoMethod*)user_data;
126         MonoMethodDesc *desc = data;
127
128         if (mono_method_desc_full_match (desc, m))
129                 break_on_method = 1;
130 }
131
132 #define DEBUG_ENTER()   \
133         fcall_count++;  \
134         g_list_foreach (db_methods, db_match_method, (gpointer)frame->method);  \
135         if (break_on_method) tracing=2; \
136         break_on_method = 0;    \
137         if (tracing) {  \
138                 MonoClass *klass = frame->method->klass;        \
139                 char *args = dump_stack (frame->stack_args, frame->stack_args+signature->param_count);  \
140                 debug_indent_level++;   \
141                 output_indent ();       \
142                 g_print ("(%d) Entering %s.%s::%s (", GetCurrentThreadId(), klass->name_space, klass->name, frame->method->name);       \
143                 if (signature->hasthis) { \
144                         if (global_no_pointers) { \
145                                 g_print ("this%s ", frame->obj ? "" : "=null"); \
146                         } else { \
147                                 g_print ("%p ", frame->obj); } \
148                 } \
149                 g_print ("%s)\n", args);        \
150                 g_free (args);  \
151         }       \
152         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
153                 mono_profiler_method_enter (frame->method);
154
155 #define DEBUG_LEAVE()   \
156         if (tracing) {  \
157                 MonoClass *klass = frame->method->klass;        \
158                 char *args;     \
159                 if (signature->ret->type != MONO_TYPE_VOID)     \
160                         args = dump_stack (frame->retval, frame->retval + 1);   \
161                 else    \
162                         args = g_strdup ("");   \
163                 output_indent ();       \
164                 g_print ("(%d) Leaving %s.%s::%s", GetCurrentThreadId(), klass->name_space, klass->name, frame->method->name);  \
165                 g_print (" => %s\n", args);     \
166                 g_free (args);  \
167                 debug_indent_level--;   \
168         }       \
169         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
170                 mono_profiler_method_leave (frame->method);
171
172 #else
173
174 #define DEBUG_ENTER()
175 #define DEBUG_LEAVE()
176
177 #endif
178
179 static void
180 interp_ex_handler (MonoException *ex) {
181         MonoInvocation *frame = TlsGetValue (frame_thread_id);
182         frame->ex = ex;
183         longjmp (*(jmp_buf*)frame->locals, 1);
184 }
185
186 static void
187 ves_real_abort (int line, MonoMethod *mh,
188                 const unsigned char *ip, stackval *stack, stackval *sp)
189 {
190         MonoMethodNormal *mm = (MonoMethodNormal *)mh;
191         fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
192         fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
193                  ip-mm->header->code);
194         g_print ("0x%04x %02x\n",
195                  ip-mm->header->code, *ip);
196         if (sp > stack)
197                 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
198 }
199 #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);
200
201 static gpointer
202 interp_create_remoting_trampoline (MonoMethod *method)
203 {
204         return method;
205 }
206
207 static MonoMethod*
208 get_virtual_method (MonoDomain *domain, MonoMethod *m, stackval *objs)
209 {
210         MonoObject *obj;
211         MonoClass *klass;
212         MonoMethod **vtable;
213
214         if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL))
215                         return m;
216
217         obj = objs->data.p;
218         klass = obj->vtable->klass;
219         vtable = (MonoMethod **)obj->vtable->vtable;
220
221         if (m->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
222                 return *(MonoMethod**)((char*)obj->vtable->interface_offsets [m->klass->interface_id] + (m->slot<<2));
223         }
224
225         g_assert (vtable [m->slot]);
226
227         return vtable [m->slot];
228 }
229
230 void inline
231 stackval_from_data (MonoType *type, stackval *result, char *data)
232 {
233         if (type->byref) {
234                 switch (type->type) {
235                 case MONO_TYPE_OBJECT:
236                 case MONO_TYPE_CLASS:
237                 case MONO_TYPE_STRING:
238                 case MONO_TYPE_ARRAY:
239                 case MONO_TYPE_SZARRAY:
240                         result->type = VAL_OBJ;
241                         break;
242                 default:
243                         result->type = VAL_VALUETA;
244                         break;
245                 }
246                 result->data.p = *(gpointer*)data;
247                 result->data.vt.klass = mono_class_from_mono_type (type);
248                 return;
249         }
250         switch (type->type) {
251         case MONO_TYPE_VOID:
252                 return;
253         case MONO_TYPE_I1:
254                 result->type = VAL_I32;
255                 result->data.i = *(gint8*)data;
256                 return;
257         case MONO_TYPE_U1:
258         case MONO_TYPE_BOOLEAN:
259                 result->type = VAL_I32;
260                 result->data.i = *(guint8*)data;
261                 return;
262         case MONO_TYPE_I2:
263                 result->type = VAL_I32;
264                 result->data.i = *(gint16*)data;
265                 return;
266         case MONO_TYPE_U2:
267         case MONO_TYPE_CHAR:
268                 result->type = VAL_I32;
269                 result->data.i = *(guint16*)data;
270                 return;
271         case MONO_TYPE_I4:
272                 result->type = VAL_I32;
273                 result->data.i = *(gint32*)data;
274                 return;
275         case MONO_TYPE_U:
276         case MONO_TYPE_I:
277         case MONO_TYPE_PTR:
278                 result->type = VAL_TP;
279                 result->data.p = *(gpointer*)data;
280                 return;
281         case MONO_TYPE_U4:
282                 result->type = VAL_I32;
283                 result->data.i = *(guint32*)data;
284                 return;
285         case MONO_TYPE_R4:
286                 result->type = VAL_DOUBLE;
287                 result->data.f = *(float*)data;
288                 return;
289         case MONO_TYPE_I8:
290         case MONO_TYPE_U8:
291                 result->type = VAL_I64;
292                 result->data.l = *(gint64*)data;
293                 return;
294         case MONO_TYPE_R8:
295                 result->type = VAL_DOUBLE;
296                 result->data.f = *(double*)data;
297                 return;
298         case MONO_TYPE_STRING:
299         case MONO_TYPE_SZARRAY:
300         case MONO_TYPE_CLASS:
301         case MONO_TYPE_OBJECT:
302         case MONO_TYPE_ARRAY:
303                 result->type = VAL_OBJ;
304                 result->data.p = *(gpointer*)data;
305                 result->data.vt.klass = mono_class_from_mono_type (type);
306                 return;
307         case MONO_TYPE_VALUETYPE:
308                 if (type->data.klass->enumtype) {
309                         return stackval_from_data (type->data.klass->enum_basetype, result, data);
310                 } else {
311                         result->type = VAL_VALUET;
312                         result->data.vt.klass = type->data.klass;
313                         memcpy (result->data.vt.vt, data, mono_class_value_size (type->data.klass, NULL));
314                 }
315                 return;
316         default:
317                 g_warning ("got type 0x%02x", type->type);
318                 g_assert_not_reached ();
319         }
320 }
321
322 static void inline
323 stackval_to_data (MonoType *type, stackval *val, char *data)
324 {
325         if (type->byref) {
326                 gpointer *p = (gpointer*)data;
327                 *p = val->data.p;
328                 return;
329         }
330         switch (type->type) {
331         case MONO_TYPE_I1:
332         case MONO_TYPE_U1: {
333                 guint8 *p = (guint8*)data;
334                 *p = val->data.i;
335                 return;
336         }
337         case MONO_TYPE_BOOLEAN: {
338                 guint8 *p = (guint8*)data;
339                 *p = (val->data.i != 0);
340                 return;
341         }
342         case MONO_TYPE_I2:
343         case MONO_TYPE_U2:
344         case MONO_TYPE_CHAR: {
345                 guint16 *p = (guint16*)data;
346                 *p = val->data.i;
347                 return;
348         }
349 #if SIZEOF_VOID_P == 4
350         case MONO_TYPE_I:
351         case MONO_TYPE_U:
352 #endif
353         case MONO_TYPE_I4:
354         case MONO_TYPE_U4: {
355                 gint32 *p = (gint32*)data;
356                 *p = val->data.i;
357                 return;
358         }
359 #if SIZEOF_VOID_P == 8
360         case MONO_TYPE_I:
361         case MONO_TYPE_U:
362 #endif
363         case MONO_TYPE_I8:
364         case MONO_TYPE_U8: {
365                 gint64 *p = (gint64*)data;
366                 *p = val->data.l;
367                 return;
368         }
369         case MONO_TYPE_R4: {
370                 float *p = (float*)data;
371                 *p = val->data.f;
372                 return;
373         }
374         case MONO_TYPE_R8: {
375                 double *p = (double*)data;
376                 *p = val->data.f;
377                 return;
378         }
379         case MONO_TYPE_STRING:
380         case MONO_TYPE_SZARRAY:
381         case MONO_TYPE_CLASS:
382         case MONO_TYPE_OBJECT:
383         case MONO_TYPE_ARRAY:
384         case MONO_TYPE_PTR: {
385                 gpointer *p = (gpointer*)data;
386                 *p = val->data.p;
387                 return;
388         }
389         case MONO_TYPE_VALUETYPE:
390                 if (type->data.klass->enumtype) {
391                         return stackval_to_data (type->data.klass->enum_basetype, val, data);
392                 } else {
393                         memcpy (data, val->data.vt.vt, mono_class_value_size (type->data.klass, NULL));
394                 }
395                 return;
396         default:
397                 g_warning ("got type %x", type->type);
398                 g_assert_not_reached ();
399         }
400 }
401
402 static MonoObject*
403 ves_array_create (MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
404 {
405         guint32 *lengths;
406         guint32 *lower_bounds;
407         int i;
408
409         lengths = alloca (sizeof (guint32) * klass->rank * 2);
410         for (i = 0; i < sig->param_count; ++i) {
411                 lengths [i] = values->data.i;
412                 values ++;
413         }
414         if (klass->rank == sig->param_count) {
415                 /* Only lengths provided. */
416                 lower_bounds = NULL;
417         } else {
418                 /* lower bounds are first. */
419                 lower_bounds = lengths;
420                 lengths += klass->rank;
421         }
422         return (MonoObject*)mono_array_new_full (domain, klass, lengths, lower_bounds);
423 }
424
425 static void 
426 ves_array_set (MonoInvocation *frame)
427 {
428         stackval *sp = frame->stack_args;
429         MonoObject *o;
430         MonoArray *ao;
431         MonoClass *ac;
432         gint32 i, t, pos, esize;
433         gpointer ea;
434         MonoType *mt;
435
436         o = frame->obj;
437         ao = (MonoArray *)o;
438         ac = o->vtable->klass;
439
440         g_assert (ac->rank >= 1);
441
442         pos = sp [0].data.i;
443         if (ao->bounds != NULL) {
444                 pos -= ao->bounds [0].lower_bound;
445                 for (i = 1; i < ac->rank; i++) {
446                         if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >= 
447                             ao->bounds [i].length) {
448                                 g_warning ("wrong array index");
449                                 g_assert_not_reached ();
450                         }
451                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
452                                 ao->bounds [i].lower_bound;
453                 }
454         }
455
456         esize = mono_array_element_size (ac);
457         ea = mono_array_addr_with_size (ao, esize, pos);
458
459         mt = frame->method->signature->params [ac->rank];
460         stackval_to_data (mt, &sp [ac->rank], ea);
461 }
462
463 static void 
464 ves_array_get (MonoInvocation *frame)
465 {
466         stackval *sp = frame->stack_args;
467         MonoObject *o;
468         MonoArray *ao;
469         MonoClass *ac;
470         gint32 i, pos, esize;
471         gpointer ea;
472         MonoType *mt;
473
474         o = frame->obj;
475         ao = (MonoArray *)o;
476         ac = o->vtable->klass;
477
478         g_assert (ac->rank >= 1);
479
480         pos = sp [0].data.i;
481         if (ao->bounds != NULL) {
482                 pos -= ao->bounds [0].lower_bound;
483                 for (i = 1; i < ac->rank; i++)
484                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
485                                 ao->bounds [i].lower_bound;
486         }
487
488         esize = mono_array_element_size (ac);
489         ea = mono_array_addr_with_size (ao, esize, pos);
490
491         mt = frame->method->signature->ret;
492         stackval_from_data (mt, frame->retval, ea);
493 }
494
495 static void
496 ves_array_element_address (MonoInvocation *frame)
497 {
498         stackval *sp = frame->stack_args;
499         MonoObject *o;
500         MonoArray *ao;
501         MonoClass *ac;
502         gint32 i, pos, esize;
503         gpointer ea;
504
505         o = frame->obj;
506         ao = (MonoArray *)o;
507         ac = o->vtable->klass;
508
509         g_assert (ac->rank >= 1);
510
511         pos = sp [0].data.i;
512         if (ao->bounds != NULL) {
513                 pos -= ao->bounds [0].lower_bound;
514                 for (i = 1; i < ac->rank; i++)
515                         pos = pos*ao->bounds [i].length + sp [i].data.i - 
516                                 ao->bounds [i].lower_bound;
517         }
518
519         esize = mono_array_element_size (ac);
520         ea = mono_array_addr_with_size (ao, esize, pos);
521
522         frame->retval->type = VAL_TP;
523         frame->retval->data.p = ea;
524 }
525
526 static void 
527 ves_pinvoke_method (MonoInvocation *frame)
528 {
529         jmp_buf env;
530         MonoPIFunc func;
531         
532         if (setjmp(env)) {
533                 TlsSetValue (frame_thread_id, frame->args);
534                 return;
535         }
536         if (!frame->method->info)
537                 frame->method->info = mono_create_trampoline (frame->method, 0);
538         func = (MonoPIFunc)frame->method->info;
539
540         /* 
541          * frame->locals and args are unused for P/Invoke methods, so we reuse them. 
542          * locals will point to the jmp_buf, while args will point to the previous
543          * MonoInvocation frame: this is needed to make exception searching work across
544          * managed/unmanaged boundaries.
545          */
546         frame->locals = (char*)&env;
547         frame->args = (char*)TlsGetValue (frame_thread_id);
548         TlsSetValue (frame_thread_id, frame);
549
550         func ((MonoFunc)frame->method->addr, &frame->retval->data.p, frame->obj, frame->stack_args);
551         stackval_from_data (frame->method->signature->ret, frame->retval, (char*)&frame->retval->data.p);
552         TlsSetValue (frame_thread_id, frame->args);
553 }
554
555 /*
556  * From the spec:
557  * runtime specifies that the implementation of the method is automatically
558  * provided by the runtime and is primarily used for the methods of delegates.
559  */
560 static void
561 ves_runtime_method (MonoInvocation *frame)
562 {
563         const char *name = frame->method->name;
564         MonoObject *obj = (MonoObject*)frame->obj;
565         MonoMulticastDelegate *delegate = (MonoMulticastDelegate*)frame->obj;
566         MonoInvocation call;
567
568         mono_class_init (mono_defaults.multicastdelegate_class);
569         
570         if (*name == '.' && (strcmp (name, ".ctor") == 0) && obj &&
571                         mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
572                 delegate->delegate.target = frame->stack_args[0].data.p;
573                 delegate->delegate.method_ptr = frame->stack_args[1].data.p;
574                 delegate->delegate.method_info = mono_method_get_object (mono_object_domain(delegate), mono_method_pointer_get (delegate->delegate.method_ptr));
575                 return;
576         }
577         if (*name == 'I' && (strcmp (name, "Invoke") == 0) && obj &&
578                         mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
579                 guchar *code;
580                 MonoMethod *method;
581                 
582                 while (delegate) {
583
584                         code = (guchar*)delegate->delegate.method_ptr;
585                         method = mono_method_pointer_get (code);
586 #if 1
587                         /* FIXME: check for NULL method */
588                         INIT_FRAME(&call,frame,delegate->delegate.target,frame->stack_args,frame->retval,method);
589                         ves_exec_method (&call);
590 #else
591                         if (!method->addr)
592                                 method->addr = mono_create_trampoline (method, 1);
593                         func = method->addr;
594                         /* FIXME: need to handle exceptions across managed/unmanaged boundaries */
595                         func ((MonoFunc)delegate->method_ptr, &frame->retval->data.p, delegate->target, frame->stack_args);
596                         stackval_from_data (frame->method->signature->ret, frame->retval, (char*)&frame->retval->data.p);
597 #endif
598                         delegate = delegate->prev;
599                 }
600                 return;
601         }
602         g_error ("Don't know how to exec runtime method %s.%s::%s", 
603                         frame->method->klass->name_space, frame->method->klass->name,
604                         frame->method->name);
605 }
606
607 static char*
608 dump_stack (stackval *stack, stackval *sp)
609 {
610         stackval *s = stack;
611         GString *str = g_string_new ("");
612         
613         if (sp == stack)
614                 return g_string_free (str, FALSE);
615         
616         while (s < sp) {
617                 switch (s->type) {
618                 case VAL_I32: g_string_sprintfa (str, "[%d] ", s->data.i); break;
619                 case VAL_I64: g_string_sprintfa (str, "[%lld] ", s->data.l); break;
620                 case VAL_DOUBLE: g_string_sprintfa (str, "[%0.5f] ", s->data.f); break;
621                 case VAL_VALUET:
622                         if (!global_no_pointers)
623                                 g_string_sprintfa (str, "[vt: %p] ", s->data.vt.vt);
624                         else
625                                 g_string_sprintfa (str, "[vt%s] ", s->data.vt.vt ? "" : "=null");
626                         break;
627 #if 0
628                 case VAL_OBJ: {
629                         MonoObject *obj =  s->data.p;
630                         if (obj && obj->klass == mono_defaults.string_class) {
631                                 char *str = mono_string_to_utf8 ((MonoString*)obj);
632                                 printf ("\"%s\" ", str);
633                                 g_free (str);
634                                 break;
635                         }
636                 }
637 #endif
638                 default:
639                         if (!global_no_pointers)
640                                 g_string_sprintfa (str, "[%p] ", s->data.p);
641                         else
642                                 g_string_sprintfa (str, s->data.p ? "[ptr] " : "[null] ");
643                         break;
644                 }
645                 ++s;
646         }
647         return g_string_free (str, FALSE);
648 }
649
650 static char*
651 dump_frame (MonoInvocation *inv)
652 {
653         GString *str = g_string_new ("");
654         int i;
655         char *args;
656         for (i = 0; inv; inv = inv->parent, ++i) {
657                 MonoClass *k = inv->method->klass;
658                 int codep;
659                 const char * opname;
660                 if (inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL ||
661                                 inv->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
662                         codep = 0;
663                         opname = "";
664                 } else {
665                         MonoMethodHeader *hd = ((MonoMethodNormal *)inv->method)->header;
666                         if (inv->ip)
667                                 codep = *(inv->ip) == 0xfe? inv->ip [1] + 256: *(inv->ip);
668                         else
669                                 codep = 0;
670                         opname = mono_opcode_names [codep];
671                         codep = inv->ip - hd->code;
672                 }
673                 args = dump_stack (inv->stack_args, inv->stack_args + inv->method->signature->param_count);
674                 g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s.%s::%s (%s)\n", i, codep, opname,
675                                                 k->name_space, k->name, inv->method->name, args);
676                 g_free (args);
677         }
678         return g_string_free (str, FALSE);
679 }
680
681 static CRITICAL_SECTION metadata_lock;
682
683 typedef enum {
684         INLINE_STRING_LENGTH = 1,
685         INLINE_ARRAY_LENGTH,
686         INLINE_ARRAY_RANK,
687         INLINE_TYPE_ELEMENT_TYPE
688 } InlineMethod;
689
690 static void
691 calc_offsets (MonoImage *image, MonoMethod *method)
692 {
693         int i, align, size, offset = 0;
694         MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
695         MonoMethodSignature *signature = method->signature;
696         int hasthis = signature->hasthis;
697         register const unsigned char *ip, *end;
698         const MonoOpcode *opcode;
699         guint32 token;
700         MonoMethod *m;
701         MonoClass *class;
702         MonoDomain *domain = mono_domain_get ();
703         guint32 *offsets;
704
705         mono_profiler_method_jit (method); /* sort of... */
706         offsets = g_new0 (guint32, 2 + header->num_locals + signature->param_count + signature->hasthis);
707         for (i = 0; i < header->num_locals; ++i) {
708                 size = mono_type_size (header->locals [i], &align);
709                 offset += align - 1;
710                 offset &= ~(align - 1);
711                 offsets [2 + i] = offset;
712                 offset += size;
713         }
714         offsets [0] = offset;
715         offset = 0;
716         if (hasthis) {
717                 offset += sizeof (gpointer) - 1;
718                 offset &= ~(sizeof (gpointer) - 1);
719                 offsets [2 + header->num_locals] = offset;
720                 offset += sizeof (gpointer);
721         }
722         for (i = 0; i < signature->param_count; ++i) {
723                 size = mono_type_size (signature->params [i], &align);
724                 offset += align - 1;
725                 offset &= ~(align - 1);
726                 offsets [2 + hasthis + header->num_locals + i] = offset;
727                 offset += size;
728         }
729         offsets [1] = offset;
730
731         EnterCriticalSection (&metadata_lock);
732         /* intern the strings in the method. */
733         ip = header->code;
734         end = ip + header->code_size;
735         while (ip < end) {
736                 i = *ip;
737                 if (*ip == 0xfe) {
738                         ip++;
739                         i = *ip + 256;
740                 }
741                 opcode = &mono_opcodes [i];
742                 switch (opcode->argument) {
743                 case MonoInlineNone:
744                         ++ip;
745                         break;
746                 case MonoInlineString:
747                         mono_ldstr (domain, image, mono_metadata_token_index (read32 (ip + 1)));
748                         ip += 5;
749                         break;
750                 case MonoInlineType:
751                         class = mono_class_get (image, read32 (ip + 1));
752                         mono_class_init (class);
753                         if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE))
754                                 mono_class_vtable (domain, class);
755                         ip += 5;
756                         break;
757                 case MonoInlineField:
758                         token = read32 (ip + 1);
759                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
760                                 mono_field_from_memberref (image, token, &class);
761                         } else {
762                                 class = mono_class_get (image, 
763                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
764                         }
765                         mono_class_init (class);
766                         mono_class_vtable (domain, class);
767                         ip += 5;
768                         break;
769                 case MonoInlineMethod:
770                         m = mono_get_method (image, read32 (ip + 1), NULL);
771                         mono_class_init (m->klass);
772                         if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
773                                 mono_class_vtable (domain, m->klass);
774                         ip += 5;
775                         break;
776                 case MonoInlineTok:
777                 case MonoInlineSig:
778                 case MonoShortInlineR:
779                 case MonoInlineI:
780                 case MonoInlineBrTarget:
781                         ip += 5;
782                         break;
783                 case MonoInlineVar:
784                         ip += 3;
785                         break;
786                 case MonoShortInlineVar:
787                 case MonoShortInlineI:
788                 case MonoShortInlineBrTarget:
789                         ip += 2;
790                         break;
791                 case MonoInlineSwitch: {
792                         guint32 n;
793                         ++ip;
794                         n = read32 (ip);
795                         ip += 4;
796                         ip += 4 * n;
797                         break;
798                 }
799                 case MonoInlineR:
800                 case MonoInlineI8:
801                         ip += 9;
802                         break;
803                 default:
804                         g_assert_not_reached ();
805                 }
806
807         }
808         method->info = offsets;
809
810         /*
811          * We store the inline info in addr, since it's unused for IL methods.
812          */
813         if (method->klass == mono_defaults.string_class) {
814                 if (strcmp (method->name, "get_Length") == 0)
815                         method->addr = GUINT_TO_POINTER (INLINE_STRING_LENGTH);
816         } else if (method->klass == mono_defaults.array_class) {
817                 if (strcmp (method->name, "get_Length") == 0)
818                         method->addr = GUINT_TO_POINTER (INLINE_ARRAY_LENGTH);
819                 else if (strcmp (method->name, "get_Rank") == 0 || strcmp (method->name, "GetRank") == 0)
820                         method->addr = GUINT_TO_POINTER (INLINE_ARRAY_RANK);
821         } else if (method->klass == mono_defaults.monotype_class) {
822                 if (strcmp (method->name, "GetElementType") == 0)
823                         method->addr = GUINT_TO_POINTER (INLINE_TYPE_ELEMENT_TYPE);
824         }
825         LeaveCriticalSection (&metadata_lock);
826         mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
827 }
828
829 #define LOCAL_POS(n)            (frame->locals + offsets [2 + (n)])
830 #define LOCAL_TYPE(header, n)   ((header)->locals [(n)])
831
832 #define ARG_POS(n)              (args_pointers [(n)])
833 #define ARG_TYPE(sig, n)        ((n) ? (sig)->params [(n) - (sig)->hasthis] : \
834                                 (sig)->hasthis ? &frame->method->klass->this_arg: (sig)->params [(0)])
835
836 #define THROW_EX(exception,ex_ip)       \
837                 do {\
838                         char *stack_trace;      \
839                         frame->ip = (ex_ip);            \
840                         stack_trace = dump_frame (frame);       \
841                         frame->ex = (MonoException*)(exception);        \
842                         frame->ex->stack_trace = mono_string_new (domain, stack_trace); \
843                         g_free (stack_trace);   \
844                         goto handle_exception;  \
845                 } while (0)
846
847 typedef struct _vtallocation vtallocation;
848
849 struct _vtallocation {
850         vtallocation *next;
851         guint32 size;
852         char data [MONO_ZERO_LEN_ARRAY];
853 };
854
855 /*
856  * we don't use vtallocation->next, yet
857  */
858 #define vt_alloc(vtype,sp)      \
859         if ((vtype)->type == MONO_TYPE_VALUETYPE && !(vtype)->data.klass->enumtype) {   \
860                 if (!(vtype)->byref) {  \
861                         guint32 align;  \
862                         guint32 size = mono_class_value_size ((vtype)->data.klass, &align);     \
863                         if (!vtalloc || vtalloc->size <= size) {        \
864                                 vtalloc = alloca (sizeof (vtallocation) + size);        \
865                                 vtalloc->size = size;   \
866                                 g_assert (size < 10000);        \
867                         }       \
868                         (sp)->data.vt.vt = vtalloc->data;       \
869                         vtalloc = NULL; \
870                 } else {        \
871                         (sp)->data.vt.klass = (vtype)->data.klass;      \
872                 }       \
873         }
874
875 #define vt_free(sp)     \
876         do {    \
877                 if ((sp)->type == VAL_VALUET) { \
878                         vtalloc = (vtallocation*)(((char*)(sp)->data.vt.vt) - G_STRUCT_OFFSET (vtallocation, data));    \
879                 }       \
880         } while (0)
881
882 static void
883 verify_method (MonoMethod *m)
884 {
885         GSList *errors, *tmp;
886         MonoVerifyInfo *info;
887
888         errors = mono_method_verify (m, MONO_VERIFY_ALL);
889         if (errors)
890                 g_print ("Method %s.%s::%s has invalid IL.\n", m->klass->name_space, m->klass->name, m->name);
891         for (tmp = errors; tmp; tmp = tmp->next) {
892                 info = tmp->data;
893                 g_print ("%s\n", info->message);
894         }
895         if (errors)
896                 G_BREAKPOINT ();
897         mono_free_verify_list (errors);
898 }
899
900 #define MYGUINT64_MAX 18446744073709551615UL
901 #define MYGINT64_MAX 9223372036854775807LL
902 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
903
904 #define MYGUINT32_MAX 4294967295U
905 #define MYGINT32_MAX 2147483647
906 #define MYGINT32_MIN (-MYGINT32_MAX -1)
907         
908 #define CHECK_ADD_OVERFLOW(a,b) \
909         (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0  \
910         : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
911
912 #define CHECK_ADD_OVERFLOW_UN(a,b) \
913         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
914
915 #define CHECK_ADD_OVERFLOW64(a,b) \
916         (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0  \
917         : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
918
919 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
920         (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
921
922 static MonoObject*
923 interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params,
924                             MonoObject **exc)
925 {
926         MonoInvocation frame;
927         MonoObject *retval = NULL;
928         MonoMethodSignature *sig = method->signature;
929         MonoClass *klass = mono_class_from_mono_type (sig->ret);
930         int i, type, isobject = 0;
931         void *ret;
932         stackval result;
933         stackval *args = alloca (sizeof (stackval) * sig->param_count);
934
935         /* FIXME: Set frame for execption handling.  */
936
937         switch (sig->ret->type) {
938         case MONO_TYPE_VOID:
939                 break;
940         case MONO_TYPE_STRING:
941         case MONO_TYPE_OBJECT:
942         case MONO_TYPE_CLASS:
943         case MONO_TYPE_ARRAY:
944         case MONO_TYPE_SZARRAY:
945                 isobject = 1;
946                 break;
947         case MONO_TYPE_VALUETYPE:
948                 retval = mono_object_new (mono_domain_get (), klass);
949                 ret = ((char*)retval) + sizeof (MonoObject);
950                 if (!sig->ret->data.klass->enumtype)
951                         result.data.vt.vt = ret;
952                 break;
953         default:
954                 retval = mono_object_new (mono_domain_get (), klass);
955                 ret = ((char*)retval) + sizeof (MonoObject);
956                 break;
957         }
958
959         for (i = 0; i < sig->param_count; ++i) {
960                 if (sig->params [i]->byref) {
961                         args [i].type = VAL_POINTER;
962                         args [i].data.p = params [i];
963                         continue;
964                 }
965                 type = sig->params [i]->type;
966 handle_enum:
967                 switch (type) {
968                 case MONO_TYPE_U1:
969                 case MONO_TYPE_I1:
970                 case MONO_TYPE_BOOLEAN:
971                         args [i].type = VAL_I32;
972                         args [i].data.i = *(MonoBoolean*)params [i];
973                         args [i].data.vt.klass = NULL;
974                         break;
975                 case MONO_TYPE_U2:
976                 case MONO_TYPE_I2:
977                 case MONO_TYPE_CHAR:
978                         args [i].type = VAL_I32;
979                         args [i].data.i = *(gint16*)params [i];
980                         args [i].data.vt.klass = NULL;
981                         break;
982 #if SIZEOF_VOID_P == 4
983                 case MONO_TYPE_U: /* use VAL_POINTER? */
984                 case MONO_TYPE_I:
985 #endif
986                 case MONO_TYPE_U4:
987                 case MONO_TYPE_I4:
988                         args [i].type = VAL_I32;
989                         args [i].data.i = *(gint32*)params [i];
990                         args [i].data.vt.klass = NULL;
991                         break;
992 #if SIZEOF_VOID_P == 8
993                 case MONO_TYPE_U:
994                 case MONO_TYPE_I:
995 #endif
996                 case MONO_TYPE_U8:
997                 case MONO_TYPE_I8:
998                         args [i].type = VAL_I64;
999                         args [i].data.l = *(gint64*)params [i];
1000                         args [i].data.vt.klass = NULL;
1001                         break;
1002                 case MONO_TYPE_VALUETYPE:
1003                         if (sig->params [i]->data.klass->enumtype) {
1004                                 type = sig->params [i]->data.klass->enum_basetype->type;
1005                                 goto handle_enum;
1006                         } else {
1007                                 g_warning ("generic valutype %s not handled in runtime invoke", sig->params [i]->data.klass->name);
1008                         }
1009                         break;
1010                 case MONO_TYPE_STRING:
1011                 case MONO_TYPE_CLASS:
1012                 case MONO_TYPE_ARRAY:
1013                 case MONO_TYPE_SZARRAY:
1014                 case MONO_TYPE_OBJECT:
1015                         args [i].type = VAL_OBJ;
1016                         args [i].data.p = params [i];
1017                         args [i].data.vt.klass = NULL;
1018                         break;
1019                 default:
1020                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1021                 }
1022         }
1023
1024         INIT_FRAME(&frame,NULL,obj,args,&result,method);
1025         ves_exec_method (&frame);
1026         if (sig->ret->type == MONO_TYPE_VOID)
1027                 return NULL;
1028         if (isobject)
1029                 return result.data.p;
1030         stackval_to_data (sig->ret, &result, ret);
1031         return retval;
1032 }
1033
1034 /*
1035  * Need to optimize ALU ops when natural int == int32 
1036  *
1037  * IDEA: if we maintain a stack of ip, sp to be checked
1038  * in the return opcode, we could inline simple methods that don't
1039  * use the stack or local variables....
1040  * 
1041  * The {,.S} versions of many opcodes can/should be merged to reduce code
1042  * duplication.
1043  * 
1044  */
1045 void 
1046 ves_exec_method (MonoInvocation *frame)
1047 {
1048         MonoDomain *domain = mono_domain_get ();        
1049         MonoInvocation child_frame;
1050         MonoMethodHeader *header;
1051         MonoMethodSignature *signature;
1052         MonoImage *image;
1053         GSList *finally_ips = NULL;
1054         const unsigned char *endfinally_ip;
1055         register const unsigned char *ip;
1056         register stackval *sp;
1057         void **args_pointers;
1058         guint32 *offsets;
1059         gint il_ins_count = -1;
1060         gint tracing = global_tracing;
1061         unsigned char tail_recursion = 0;
1062         unsigned char unaligned_address = 0;
1063         unsigned char volatile_address = 0;
1064         vtallocation *vtalloc = NULL;
1065         GOTO_LABEL_VARS;
1066
1067         signature = frame->method->signature;
1068
1069         DEBUG_ENTER ();
1070
1071         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
1072                 if (!frame->method->addr) {
1073                         frame->ex = (MonoException*)mono_get_exception_missing_method ();
1074                         DEBUG_LEAVE ();
1075                         return;
1076                 }
1077                 if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1078                         ves_pinvoke_method (frame);
1079                 } else {
1080                         ICallMethod icall = (ICallMethod)frame->method->addr;
1081                         icall (frame);
1082                 }
1083                 if (frame->ex)
1084                         goto handle_exception;
1085                 DEBUG_LEAVE ();
1086                 return;
1087         } 
1088
1089         if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1090                 if (!frame->method->addr) {
1091                         frame->ex = (MonoException*)mono_get_exception_missing_method ();
1092                         DEBUG_LEAVE ();
1093                         return;
1094                 }
1095                 ves_pinvoke_method (frame);
1096                 if (frame->ex)
1097                         goto handle_exception;
1098                 DEBUG_LEAVE ();
1099                 return;
1100         } 
1101
1102         if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
1103                 ves_runtime_method (frame);
1104                 if (frame->ex)
1105                         goto handle_exception;
1106                 DEBUG_LEAVE ();
1107                 return;
1108         } 
1109
1110         /*verify_method (frame->method);*/
1111
1112         header = ((MonoMethodNormal *)frame->method)->header;
1113         image = frame->method->klass->image;
1114
1115         if (!frame->method->info)
1116                 calc_offsets (image, frame->method);
1117         offsets = frame->method->info;
1118
1119         /*
1120          * with alloca we get the expected huge performance gain
1121          * stackval *stack = g_new0(stackval, header->max_stack);
1122          */
1123         g_assert (header->max_stack < 10000);
1124         sp = frame->stack = alloca (sizeof (stackval) * header->max_stack);
1125
1126         if (header->num_locals) {
1127                 g_assert (offsets [0] < 10000);
1128                 frame->locals = alloca (offsets [0]);
1129                 /* 
1130                  * yes, we do it unconditionally, because it needs to be done for
1131                  * some cases anyway and checking for that would be even slower.
1132                  */
1133                 memset (frame->locals, 0, offsets [0]);
1134         }
1135         /*
1136          * Copy args from stack_args to args.
1137          */
1138         if (signature->param_count || signature->hasthis) {
1139                 int i;
1140                 int has_this = signature->hasthis;
1141
1142                 g_assert (offsets [1] < 10000);
1143                 frame->args = alloca (offsets [1]);
1144                 g_assert ((signature->param_count + has_this) < 1000);
1145                 args_pointers = alloca (sizeof(void*) * (signature->param_count + has_this));
1146                 if (has_this) {
1147                         gpointer *this_arg;
1148                         this_arg = args_pointers [0] = frame->args;
1149                         *this_arg = frame->obj;
1150                 }
1151                 for (i = 0; i < signature->param_count; ++i) {
1152                         args_pointers [i + has_this] = frame->args + offsets [2 + header->num_locals + has_this + i];
1153                         stackval_to_data (signature->params [i], frame->stack_args + i, args_pointers [i + has_this]);
1154                 }
1155         }
1156
1157         child_frame.parent = frame;
1158         frame->child = &child_frame;
1159         frame->ex = NULL;
1160
1161         /* ready to go */
1162         ip = header->code;
1163
1164         /*
1165          * using while (ip < end) may result in a 15% performance drop, 
1166          * but it may be useful for debug
1167          */
1168         while (1) {
1169         main_loop:
1170                 /*g_assert (sp >= stack);*/
1171 #if DEBUG_INTERP
1172                 opcode_count++;
1173                 if (tracing > 1) {
1174                         char *ins;
1175                         if (sp > frame->stack) {
1176                                 output_indent ();
1177                                 ins = dump_stack (frame->stack, sp);
1178                                 g_print ("(%d) stack: %s\n", GetCurrentThreadId(), ins);
1179                                 g_free (ins);
1180                         }
1181                         output_indent ();
1182                         ins = mono_disasm_code_one (NULL, frame->method, ip);
1183                         g_print ("(%d) %s", GetCurrentThreadId(), ins);
1184                         g_free (ins);
1185                 }
1186                 if (il_ins_count > 0)
1187                         if (!(--il_ins_count))
1188                                 G_BREAKPOINT ();
1189 #endif
1190                 
1191                 SWITCH (*ip) {
1192                 CASE (CEE_NOP) 
1193                         ++ip;
1194                         BREAK;
1195                 CASE (CEE_BREAK)
1196                         ++ip;
1197                         G_BREAKPOINT (); /* this is not portable... */
1198                         BREAK;
1199                 CASE (CEE_LDARG_0)
1200                 CASE (CEE_LDARG_1)
1201                 CASE (CEE_LDARG_2)
1202                 CASE (CEE_LDARG_3) {
1203                         int n = (*ip)-CEE_LDARG_0;
1204                         ++ip;
1205                         vt_alloc (ARG_TYPE (signature, n), sp);
1206                         stackval_from_data (ARG_TYPE (signature, n), sp, ARG_POS (n));
1207                         ++sp;
1208                         BREAK;
1209                 }
1210                 CASE (CEE_LDLOC_0)
1211                 CASE (CEE_LDLOC_1)
1212                 CASE (CEE_LDLOC_2)
1213                 CASE (CEE_LDLOC_3) {
1214                         int n = (*ip)-CEE_LDLOC_0;
1215                         ++ip;
1216                         if ((LOCAL_TYPE (header, n))->type == MONO_TYPE_I4) {
1217                                 sp->type = VAL_I32;
1218                                 sp->data.i = *(gint32*) LOCAL_POS (n);
1219                                 ++sp;
1220                                 BREAK;
1221                         } else {
1222                                 vt_alloc (LOCAL_TYPE (header, n), sp);
1223                                 stackval_from_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n));
1224                         }
1225                         ++sp;
1226                         BREAK;
1227                 }
1228                 CASE (CEE_STLOC_0)
1229                 CASE (CEE_STLOC_1)
1230                 CASE (CEE_STLOC_2)
1231                 CASE (CEE_STLOC_3) {
1232                         int n = (*ip)-CEE_STLOC_0;
1233                         ++ip;
1234                         --sp;
1235                         if ((LOCAL_TYPE (header, n))->type == MONO_TYPE_I4) {
1236                                 gint32 *p = (gint32*)LOCAL_POS (n);
1237                                 *p = sp->data.i;
1238                                 BREAK;
1239                         } else {
1240                                 stackval_to_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n));
1241                                 vt_free (sp);
1242                                 BREAK;
1243                         }
1244                 }
1245                 CASE (CEE_LDARG_S)
1246                         ++ip;
1247                         vt_alloc (ARG_TYPE (signature, *ip), sp);
1248                         stackval_from_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip));
1249                         ++sp;
1250                         ++ip;
1251                         BREAK;
1252                 CASE (CEE_LDARGA_S) {
1253                         MonoType *t;
1254                         MonoClass *c;
1255
1256                         ++ip;
1257                         t = ARG_TYPE (signature, *ip);
1258                         c = mono_class_from_mono_type (t);
1259                         sp->data.vt.klass = c;
1260                         sp->data.vt.vt = ARG_POS (*ip);
1261
1262                         if (c->valuetype)
1263                                 sp->type = VAL_VALUETA;
1264                         else
1265                                 sp->type = VAL_TP;
1266
1267                         ++sp;
1268                         ++ip;
1269                         BREAK;
1270                 }
1271                 CASE (CEE_STARG_S)
1272                         ++ip;
1273                         --sp;
1274                         stackval_to_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip));
1275                         vt_free (sp);
1276                         ++ip;
1277                         BREAK;
1278                 CASE (CEE_LDLOC_S)
1279                         ++ip;
1280                         vt_alloc (LOCAL_TYPE (header, *ip), sp);
1281                         stackval_from_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip));
1282                         ++ip;
1283                         ++sp;
1284                         BREAK;
1285                 CASE (CEE_LDLOCA_S) {
1286                         MonoType *t;
1287                         MonoClass *c;
1288
1289                         ++ip;
1290                         t = LOCAL_TYPE (header, *ip);
1291                         c =  mono_class_from_mono_type (t);
1292                         sp->data.vt.klass = c;
1293                         sp->data.p = LOCAL_POS (*ip);
1294
1295                         if (c->valuetype)
1296                                 sp->type = VAL_VALUETA;
1297                         else 
1298                                 sp->type = VAL_TP;
1299
1300                         ++sp;
1301                         ++ip;
1302                         BREAK;
1303                 }
1304                 CASE (CEE_STLOC_S)
1305                         ++ip;
1306                         --sp;
1307                         stackval_to_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip));
1308                         vt_free (sp);
1309                         ++ip;
1310                         BREAK;
1311                 CASE (CEE_LDNULL) 
1312                         ++ip;
1313                         sp->type = VAL_OBJ;
1314                         sp->data.p = NULL;
1315                         sp->data.vt.klass = NULL;
1316                         ++sp;
1317                         BREAK;
1318                 CASE (CEE_LDC_I4_M1)
1319                         ++ip;
1320                         sp->type = VAL_I32;
1321                         sp->data.i = -1;
1322                         ++sp;
1323                         BREAK;
1324                 CASE (CEE_LDC_I4_0)
1325                 CASE (CEE_LDC_I4_1)
1326                 CASE (CEE_LDC_I4_2)
1327                 CASE (CEE_LDC_I4_3)
1328                 CASE (CEE_LDC_I4_4)
1329                 CASE (CEE_LDC_I4_5)
1330                 CASE (CEE_LDC_I4_6)
1331                 CASE (CEE_LDC_I4_7)
1332                 CASE (CEE_LDC_I4_8)
1333                         sp->type = VAL_I32;
1334                         sp->data.i = (*ip) - CEE_LDC_I4_0;
1335                         ++sp;
1336                         ++ip;
1337                         BREAK;
1338                 CASE (CEE_LDC_I4_S) 
1339                         ++ip;
1340                         sp->type = VAL_I32;
1341                         sp->data.i = *(const gint8 *)ip;
1342                         ++ip;
1343                         ++sp;
1344                         BREAK;
1345                 CASE (CEE_LDC_I4)
1346                         ++ip;
1347                         sp->type = VAL_I32;
1348                         sp->data.i = read32 (ip);
1349                         ip += 4;
1350                         ++sp;
1351                         BREAK;
1352                 CASE (CEE_LDC_I8)
1353                         ++ip;
1354                         sp->type = VAL_I64;
1355                         sp->data.l = read64 (ip);
1356                         ip += 8;
1357                         ++sp;
1358                         BREAK;
1359                 CASE (CEE_LDC_R4) {
1360                         float val;
1361                         ++ip;
1362                         sp->type = VAL_DOUBLE;
1363                         readr4 (ip, &val);
1364                         sp->data.f = val;
1365                         ip += 4;
1366                         ++sp;
1367                         BREAK;
1368                 }
1369                 CASE (CEE_LDC_R8) 
1370                         ++ip;
1371                         sp->type = VAL_DOUBLE;
1372                         readr8(ip, &sp->data.f);
1373                         ip += 8;
1374                         ++sp;
1375                         BREAK;
1376                 CASE (CEE_UNUSED99) ves_abort (); BREAK;
1377                 CASE (CEE_DUP) 
1378                         if (sp [-1].type == VAL_VALUET) {
1379                                 MonoClass *c = sp [-1].data.vt.klass;
1380                                 vt_alloc (&c->byval_arg, sp);
1381                                 stackval_from_data (&c->byval_arg, sp, sp [-1].data.vt.vt);
1382                         } else {
1383                                 *sp = sp [-1]; 
1384                         }
1385                         ++sp; 
1386                         ++ip; 
1387                         BREAK;
1388                 CASE (CEE_POP)
1389                         ++ip;
1390                         --sp;
1391                         vt_free (sp);
1392                         BREAK;
1393                 CASE (CEE_JMP) ves_abort(); BREAK;
1394                 CASE (CEE_CALLVIRT) /* Fall through */
1395                 CASE (CEE_CALLI)    /* Fall through */
1396                 CASE (CEE_CALL) {
1397                         MonoMethodSignature *csignature;
1398                         stackval retval;
1399                         stackval *endsp = sp;
1400                         guint32 token;
1401                         int virtual = *ip == CEE_CALLVIRT;
1402                         int calli = *ip == CEE_CALLI;
1403
1404                         /*
1405                          * We ignore tail recursion for now.
1406                          */
1407                         tail_recursion = 0;
1408
1409                         frame->ip = ip;
1410                         
1411                         ++ip;
1412                         token = read32 (ip);
1413                         ip += 4;
1414                         if (calli) {
1415                                 unsigned char *code;
1416                                 --sp;
1417                                 code = sp->data.p;
1418                                 child_frame.method = mono_method_pointer_get (code);
1419                                 /* check for NULL with native code */
1420                                 csignature = child_frame.method->signature;
1421                         } else {
1422                                 child_frame.method = mono_get_method (image, token, NULL);
1423                                 if (!child_frame.method)
1424                                         THROW_EX (mono_get_exception_missing_method (), ip -5);
1425                                 csignature = child_frame.method->signature;
1426                                 if (virtual) {
1427                                         stackval *this_arg = &sp [-csignature->param_count-1];
1428                                         if (!this_arg->data.p)
1429                                                 THROW_EX (mono_get_exception_null_reference(), ip - 5);
1430                                         child_frame.method = get_virtual_method (domain, child_frame.method, this_arg);
1431                                         if (!child_frame.method)
1432                                                 THROW_EX (mono_get_exception_missing_method (), ip -5);
1433                                 }
1434                         }
1435                         g_assert (csignature->call_convention == MONO_CALL_DEFAULT);
1436                         /* decrement by the actual number of args */
1437                         if (csignature->param_count) {
1438                                 sp -= csignature->param_count;
1439                                 child_frame.stack_args = sp;
1440                         } else {
1441                                 child_frame.stack_args = NULL;
1442                         }
1443                         if (csignature->hasthis) {
1444                                 g_assert (sp >= frame->stack);
1445                                 --sp;
1446                                 /*
1447                                  * It may also be a TP from LD(S)FLDA
1448                                  * g_assert (sp->type == VAL_OBJ || sp->type == VAL_VALUETA);
1449                                  */
1450                                 if (sp->type == VAL_OBJ && child_frame.method->klass->valuetype) /* unbox it */
1451                                         child_frame.obj = (char*)sp->data.p + sizeof (MonoObject);
1452                                 else
1453                                         child_frame.obj = sp->data.p;
1454                         } else {
1455                                 child_frame.obj = NULL;
1456                         }
1457                         if (csignature->ret->type != MONO_TYPE_VOID) {
1458                                 vt_alloc (csignature->ret, &retval);
1459                                 child_frame.retval = &retval;
1460                         } else {
1461                                 child_frame.retval = NULL;
1462                         }
1463
1464                         child_frame.ex = NULL;
1465                         child_frame.ex_handler = NULL;
1466
1467                         if (csignature->hasthis && sp->type == VAL_OBJ &&
1468                             ((MonoObject *)sp->data.p)->vtable->klass ==
1469                             mono_defaults.transparent_proxy_class) {
1470                                 /* implement remoting */
1471                                 g_assert_not_reached ();
1472                         } else {
1473                                 switch (GPOINTER_TO_UINT (child_frame.method->addr)) {
1474                                 case INLINE_STRING_LENGTH:
1475                                         retval.type = VAL_I32;
1476                                         retval.data.i = ((MonoString*)sp->data.p)->length;
1477                                         //g_print ("length of '%s' is %d\n", mono_string_to_utf8 (sp->data.p), retval.data.i);
1478                                         break;
1479                                 case INLINE_ARRAY_LENGTH:
1480                                         retval.type = VAL_I32;
1481                                         retval.data.i = mono_array_length ((MonoArray*)sp->data.p);
1482                                         break;
1483                                 case INLINE_ARRAY_RANK:
1484                                         retval.type = VAL_I32;
1485                                         retval.data.i = mono_object_class (sp->data.p)->rank;
1486                                         break;
1487                                 case INLINE_TYPE_ELEMENT_TYPE:
1488                                         retval.type = VAL_OBJ;
1489                                         {
1490                                                 MonoClass *c = mono_class_from_mono_type (((MonoReflectionType*)sp->data.p)->type);
1491                                                 retval.data.vt.klass = NULL;
1492                                                 if (c->enumtype && c->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
1493                                                         retval.data.p = mono_type_get_object (domain, c->enum_basetype);
1494                                                 else if (c->element_class)
1495                                                         retval.data.p = mono_type_get_object (domain, &c->element_class->byval_arg);
1496                                                 else
1497                                                         retval.data.p = NULL;
1498                                         }
1499                                         break;
1500                                 default:
1501                                         ves_exec_method (&child_frame);
1502                                 }
1503                         }
1504
1505                         while (endsp > sp) {
1506                                 --endsp;
1507                                 vt_free (endsp);
1508                         }
1509
1510                         if (child_frame.ex) {
1511                                 /*
1512                                  * An exception occurred, need to run finally, fault and catch handlers..
1513                                  */
1514                                 frame->ex = child_frame.ex;
1515                                 goto handle_finally;
1516                         }
1517
1518                         /* need to handle typedbyref ... */
1519                         if (csignature->ret->type != MONO_TYPE_VOID) {
1520                                 *sp = retval;
1521                                 sp++;
1522                         }
1523                         BREAK;
1524                 }
1525                 CASE (CEE_RET)
1526                         if (signature->ret->type != MONO_TYPE_VOID) {
1527                                 --sp;
1528                                 if (sp->type == VAL_VALUET) {
1529                                         /* the caller has already allocated the memory */
1530                                         stackval_from_data (signature->ret, frame->retval, sp->data.vt.vt);
1531                                         vt_free (sp);
1532                                 } else {
1533                                         *frame->retval = *sp;
1534                                 }
1535                         }
1536                         if (sp > frame->stack)
1537                                 g_warning ("more values on stack: %d", sp-frame->stack);
1538
1539                         DEBUG_LEAVE ();
1540                         return;
1541                 CASE (CEE_BR_S) /* Fall through */
1542                 CASE (CEE_BR)
1543                         if (*ip == CEE_BR) {
1544                                 ++ip;
1545                                 ip += (gint32) read32(ip);
1546                                 ip += 4;
1547                         } else {
1548                                 ++ip;
1549                                 ip += (signed char) *ip;
1550                                 ++ip;
1551                         }
1552                         BREAK;
1553                 CASE (CEE_BRFALSE) /* Fall through */
1554                 CASE (CEE_BRFALSE_S) {
1555                         int result;
1556                         int near_jump = *ip == CEE_BRFALSE_S;
1557                         ++ip;
1558                         --sp;
1559                         switch (sp->type) {
1560                         case VAL_I32: result = sp->data.i == 0; break;
1561                         case VAL_I64: result = sp->data.l == 0; break;
1562                         case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
1563                         default: result = sp->data.p == NULL; break;
1564                         }
1565                         if (result) {
1566                                 if (near_jump)
1567                                         ip += (signed char)*ip;
1568                                 else
1569                                         ip += (gint32) read32 (ip);
1570                         }
1571                         ip += near_jump ? 1: 4;
1572                         BREAK;
1573                 }
1574                 CASE (CEE_BRTRUE) /* Fall through */
1575                 CASE (CEE_BRTRUE_S) {
1576                         int result;
1577                         int near_jump = *ip == CEE_BRTRUE_S;
1578                         ++ip;
1579                         --sp;
1580                         switch (sp->type) {
1581                         case VAL_I32: result = sp->data.i != 0; break;
1582                         case VAL_I64: result = sp->data.l != 0; break;
1583                         case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
1584                         default: result = sp->data.p != NULL; break;
1585                         }
1586                         if (result) {
1587                                 if (near_jump)
1588                                         ip += (signed char)*ip;
1589                                 else
1590                                         ip += (gint32) read32 (ip);
1591                         }
1592                         ip += near_jump ? 1: 4;
1593                         BREAK;
1594                 }
1595                 CASE (CEE_BEQ) /* Fall through */
1596                 CASE (CEE_BEQ_S) {
1597                         int result;
1598                         int near_jump = *ip == CEE_BEQ_S;
1599                         ++ip;
1600                         sp -= 2;
1601                         if (sp->type == VAL_I32)
1602                                 result = sp [0].data.i == (gint)GET_NATI (sp [1]);
1603                         else if (sp->type == VAL_I64)
1604                                 result = sp [0].data.l == sp [1].data.l;
1605                         else if (sp->type == VAL_DOUBLE)
1606                                 result = sp [0].data.f == sp [1].data.f;
1607                         else
1608                                 result = (gint)GET_NATI (sp [0]) == (gint)GET_NATI (sp [1]);
1609                         if (result) {
1610                                 if (near_jump)
1611                                         ip += (signed char)*ip;
1612                                 else
1613                                         ip += (gint32) read32 (ip);
1614                         }
1615                         ip += near_jump ? 1: 4;
1616                         BREAK;
1617                 }
1618                 CASE (CEE_BGE) /* Fall through */
1619                 CASE (CEE_BGE_S) {
1620                         int result;
1621                         int near_jump = *ip == CEE_BGE_S;
1622                         ++ip;
1623                         sp -= 2;
1624                         if (sp->type == VAL_I32)
1625                                 result = sp [0].data.i >= (gint)GET_NATI (sp [1]);
1626                         else if (sp->type == VAL_I64)
1627                                 result = sp [0].data.l >= sp [1].data.l;
1628                         else if (sp->type == VAL_DOUBLE)
1629                                 result = sp [0].data.f >= sp [1].data.f;
1630                         else
1631                                 result = (gint)GET_NATI (sp [0]) >= (gint)GET_NATI (sp [1]);
1632                         if (result) {
1633                                 if (near_jump)
1634                                         ip += (signed char)*ip;
1635                                 else
1636                                         ip += (gint32) read32 (ip);
1637                         }
1638                         ip += near_jump ? 1: 4;
1639                         BREAK;
1640                 }
1641                 CASE (CEE_BGT) /* Fall through */
1642                 CASE (CEE_BGT_S) {
1643                         int result;
1644                         int near_jump = *ip == CEE_BGT_S;
1645                         ++ip;
1646                         sp -= 2;
1647                         if (sp->type == VAL_I32)
1648                                 result = sp [0].data.i > (gint)GET_NATI (sp [1]);
1649                         else if (sp->type == VAL_I64)
1650                                 result = sp [0].data.l > sp [1].data.l;
1651                         else if (sp->type == VAL_DOUBLE)
1652                                 result = sp [0].data.f > sp [1].data.f;
1653                         else
1654                                 result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
1655                         if (result) {
1656                                 if (near_jump)
1657                                         ip += (signed char)*ip;
1658                                 else
1659                                         ip += (gint32) read32 (ip);
1660                         }
1661                         ip += near_jump ? 1: 4;
1662                         BREAK;
1663                 }
1664                 CASE (CEE_BLT) /* Fall through */
1665                 CASE (CEE_BLT_S) {
1666                         int result;
1667                         int near_jump = *ip == CEE_BLT_S;
1668                         ++ip;
1669                         sp -= 2;
1670                         if (sp->type == VAL_I32)
1671                                 result = sp[0].data.i < (gint)GET_NATI(sp[1]);
1672                         else if (sp->type == VAL_I64)
1673                                 result = sp[0].data.l < sp[1].data.l;
1674                         else if (sp->type == VAL_DOUBLE)
1675                                 result = sp[0].data.f < sp[1].data.f;
1676                         else
1677                                 result = (gint)GET_NATI(sp[0]) < (gint)GET_NATI(sp[1]);
1678                         if (result) {
1679                                 if (near_jump)
1680                                         ip += 1 + (signed char)*ip;
1681                                 else
1682                                         ip += 4 + (gint32) read32 (ip);
1683                                 BREAK;
1684                         } else {
1685                                 ip += near_jump ? 1: 4;
1686                                 BREAK;
1687                         }
1688                 }
1689                 CASE (CEE_BLE) /* fall through */
1690                 CASE (CEE_BLE_S) {
1691                         int result;
1692                         int near_jump = *ip == CEE_BLE_S;
1693                         ++ip;
1694                         sp -= 2;
1695
1696                         if (sp->type == VAL_I32)
1697                                 result = sp [0].data.i <= (gint)GET_NATI (sp [1]);
1698                         else if (sp->type == VAL_I64)
1699                                 result = sp [0].data.l <= sp [1].data.l;
1700                         else if (sp->type == VAL_DOUBLE)
1701                                 result = sp [0].data.f <= sp [1].data.f;
1702                         else {
1703                                 /*
1704                                  * FIXME: here and in other places GET_NATI on the left side 
1705                                  * _will_ be wrong when we change the macro to work on 64 bits 
1706                                  * systems.
1707                                  */
1708                                 result = (gint)GET_NATI (sp [0]) <= (gint)GET_NATI (sp [1]);
1709                         }
1710                         if (result) {
1711                                 if (near_jump)
1712                                         ip += (signed char)*ip;
1713                                 else
1714                                         ip += (gint32) read32 (ip);
1715                         }
1716                         ip += near_jump ? 1: 4;
1717                         BREAK;
1718                 }
1719                 CASE (CEE_BNE_UN) /* Fall through */
1720                 CASE (CEE_BNE_UN_S) {
1721                         int result;
1722                         int near_jump = *ip == CEE_BNE_UN_S;
1723                         ++ip;
1724                         sp -= 2;
1725                         if (sp->type == VAL_I32)
1726                                 result = (guint32)sp [0].data.i != (guint32)GET_NATI (sp [1]);
1727                         else if (sp->type == VAL_I64)
1728                                 result = (guint64)sp [0].data.l != (guint64)sp [1].data.l;
1729                         else if (sp->type == VAL_DOUBLE)
1730                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1731                                         (sp [0].data.f != sp [1].data.f);
1732                         else
1733                                 result = GET_NATI (sp [0]) != GET_NATI (sp [1]);
1734                         if (result) {
1735                                 if (near_jump)
1736                                         ip += (signed char)*ip;
1737                                 else
1738                                         ip += (gint32) read32 (ip);
1739                         }
1740                         ip += near_jump ? 1: 4;
1741                         BREAK;
1742                 }
1743                 CASE (CEE_BGE_UN) /* Fall through */
1744                 CASE (CEE_BGE_UN_S) {
1745                         int result;
1746                         int near_jump = *ip == CEE_BGE_UN_S;
1747                         ++ip;
1748                         sp -= 2;
1749                         if (sp->type == VAL_I32)
1750                                 result = (guint32)sp [0].data.i >= (guint32)GET_NATI (sp [1]);
1751                         else if (sp->type == VAL_I64)
1752                                 result = (guint64)sp [0].data.l >= (guint64)sp [1].data.l;
1753                         else if (sp->type == VAL_DOUBLE)
1754                                 result = !isless (sp [0].data.f,sp [1].data.f);
1755                         else
1756                                 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
1757                         if (result) {
1758                                 if (near_jump)
1759                                         ip += (signed char)*ip;
1760                                 else
1761                                         ip += (gint32) read32 (ip);
1762                         }
1763                         ip += near_jump ? 1: 4;
1764                         BREAK;
1765                 }
1766                 CASE (CEE_BGT_UN) /* Fall through */
1767                 CASE (CEE_BGT_UN_S) {
1768                         int result;
1769                         int near_jump = *ip == CEE_BGT_UN_S;
1770                         ++ip;
1771                         sp -= 2;
1772                         if (sp->type == VAL_I32)
1773                                 result = (guint32)sp [0].data.i > (guint32)GET_NATI (sp [1]);
1774                         else if (sp->type == VAL_I64)
1775                                 result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
1776                         else if (sp->type == VAL_DOUBLE)
1777                                 result = isgreater (sp [0].data.f, sp [1].data.f);
1778                         else
1779                                 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
1780                         if (result) {
1781                                 if (near_jump)
1782                                         ip += (signed char)*ip;
1783                                 else
1784                                         ip += (gint32) read32 (ip);
1785                         }
1786                         ip += near_jump ? 1: 4;
1787                         BREAK;
1788                 }
1789                 CASE (CEE_BLE_UN) /* Fall through */
1790                 CASE (CEE_BLE_UN_S) {
1791                         int result;
1792                         int near_jump = *ip == CEE_BLE_UN_S;
1793                         ++ip;
1794                         sp -= 2;
1795                         if (sp->type == VAL_I32)
1796                                 result = (guint32)sp [0].data.i <= (guint32)GET_NATI (sp [1]);
1797                         else if (sp->type == VAL_I64)
1798                                 result = (guint64)sp [0].data.l <= (guint64)sp [1].data.l;
1799                         else if (sp->type == VAL_DOUBLE)
1800                                 result = islessequal (sp [0].data.f, sp [1].data.f);
1801                         else
1802                                 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
1803                         if (result) {
1804                                 if (near_jump)
1805                                         ip += (signed char)*ip;
1806                                 else
1807                                         ip += (gint32) read32 (ip);
1808                         }
1809                         ip += near_jump ? 1: 4;
1810                         BREAK;
1811                 }
1812                 CASE (CEE_BLT_UN) /* Fall through */
1813                 CASE (CEE_BLT_UN_S) {
1814                         int result;
1815                         int near_jump = *ip == CEE_BLT_UN_S;
1816                         ++ip;
1817                         sp -= 2;
1818                         if (sp->type == VAL_I32)
1819                                 result = (guint32)sp[0].data.i < (guint32)GET_NATI(sp[1]);
1820                         else if (sp->type == VAL_I64)
1821                                 result = (guint64)sp[0].data.l < (guint64)sp[1].data.l;
1822                         else if (sp->type == VAL_DOUBLE)
1823                                 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1824                                         (sp [0].data.f < sp [1].data.f);
1825                         else
1826                                 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
1827                         if (result) {
1828                                 if (near_jump)
1829                                         ip += (signed char)*ip;
1830                                 else
1831                                         ip += (gint32) read32 (ip);
1832                         }
1833                         ip += near_jump ? 1: 4;
1834                         BREAK;
1835                 }
1836                 CASE (CEE_SWITCH) {
1837                         guint32 n;
1838                         const unsigned char *st;
1839                         ++ip;
1840                         n = read32 (ip);
1841                         ip += 4;
1842                         st = ip + sizeof (gint32) * n;
1843                         --sp;
1844                         if ((guint32)sp->data.i < n) {
1845                                 gint offset;
1846                                 ip += sizeof (gint32) * (guint32)sp->data.i;
1847                                 offset = read32 (ip);
1848                                 ip = st + offset;
1849                         } else {
1850                                 ip = st;
1851                         }
1852                         BREAK;
1853                 }
1854                 CASE (CEE_LDIND_I1)
1855                         ++ip;
1856                         sp[-1].type = VAL_I32;
1857                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
1858                         BREAK;
1859                 CASE (CEE_LDIND_U1)
1860                         ++ip;
1861                         sp[-1].type = VAL_I32;
1862                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
1863                         BREAK;
1864                 CASE (CEE_LDIND_I2)
1865                         ++ip;
1866                         sp[-1].type = VAL_I32;
1867                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
1868                         BREAK;
1869                 CASE (CEE_LDIND_U2)
1870                         ++ip;
1871                         sp[-1].type = VAL_I32;
1872                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
1873                         BREAK;
1874                 CASE (CEE_LDIND_I4) /* Fall through */
1875                 CASE (CEE_LDIND_U4)
1876                         ++ip;
1877                         sp[-1].type = VAL_I32;
1878                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
1879                         BREAK;
1880                 CASE (CEE_LDIND_I8)
1881                         ++ip;
1882                         sp[-1].type = VAL_I64;
1883                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
1884                         BREAK;
1885                 CASE (CEE_LDIND_I)
1886                         ++ip;
1887                         sp[-1].type = VAL_NATI;
1888                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1889                         BREAK;
1890                 CASE (CEE_LDIND_R4)
1891                         ++ip;
1892                         sp[-1].type = VAL_DOUBLE;
1893                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
1894                         BREAK;
1895                 CASE (CEE_LDIND_R8)
1896                         ++ip;
1897                         sp[-1].type = VAL_DOUBLE;
1898                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
1899                         BREAK;
1900                 CASE (CEE_LDIND_REF)
1901                         ++ip;
1902                         sp[-1].type = VAL_OBJ;
1903                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1904                         sp[-1].data.vt.klass = NULL;
1905                         BREAK;
1906                 CASE (CEE_STIND_REF) {
1907                         gpointer *p;
1908                         ++ip;
1909                         sp -= 2;
1910                         p = sp->data.p;
1911                         *p = sp[1].data.p;
1912                         BREAK;
1913                 }
1914                 CASE (CEE_STIND_I1) {
1915                         gint8 *p;
1916                         ++ip;
1917                         sp -= 2;
1918                         p = sp->data.p;
1919                         *p = (gint8)sp[1].data.i;
1920                         BREAK;
1921                 }
1922                 CASE (CEE_STIND_I2) {
1923                         gint16 *p;
1924                         ++ip;
1925                         sp -= 2;
1926                         p = sp->data.p;
1927                         *p = (gint16)sp[1].data.i;
1928                         BREAK;
1929                 }
1930                 CASE (CEE_STIND_I4) {
1931                         gint32 *p;
1932                         ++ip;
1933                         sp -= 2;
1934                         p = sp->data.p;
1935                         *p = sp[1].data.i;
1936                         BREAK;
1937                 }
1938                 CASE (CEE_STIND_I) {
1939                         mono_i *p;
1940                         ++ip;
1941                         sp -= 2;
1942                         p = sp->data.p;
1943                         *p = (mono_i)sp[1].data.p;
1944                         BREAK;
1945                 }
1946                 CASE (CEE_STIND_I8) {
1947                         gint64 *p;
1948                         ++ip;
1949                         sp -= 2;
1950                         p = sp->data.p;
1951                         *p = sp[1].data.l;
1952                         BREAK;
1953                 }
1954                 CASE (CEE_STIND_R4) {
1955                         float *p;
1956                         ++ip;
1957                         sp -= 2;
1958                         p = sp->data.p;
1959                         *p = (gfloat)sp[1].data.f;
1960                         BREAK;
1961                 }
1962                 CASE (CEE_STIND_R8) {
1963                         double *p;
1964                         ++ip;
1965                         sp -= 2;
1966                         p = sp->data.p;
1967                         *p = sp[1].data.f;
1968                         BREAK;
1969                 }
1970                 CASE (CEE_ADD)
1971                         ++ip;
1972                         --sp;
1973                         /* should probably consider the pointers as unsigned */
1974                         if (sp->type == VAL_I32)
1975                                 sp [-1].data.i += GET_NATI (sp [0]);
1976                         else if (sp->type == VAL_I64)
1977                                 sp [-1].data.l += sp [0].data.l;
1978                         else if (sp->type == VAL_DOUBLE)
1979                                 sp [-1].data.f += sp [0].data.f;
1980                         else {
1981                                 char *p = sp [-1].data.p;
1982                                 p += GET_NATI (sp [0]);
1983                                 sp [-1].data.p = p;
1984                         }
1985                         BREAK;
1986                 CASE (CEE_SUB)
1987                         ++ip;
1988                         --sp;
1989                         /* should probably consider the pointers as unsigned */
1990                         if (sp->type == VAL_I32)
1991                                 sp [-1].data.i -= GET_NATI (sp [0]);
1992                         else if (sp->type == VAL_I64)
1993                                 sp [-1].data.l -= sp [0].data.l;
1994                         else if (sp->type == VAL_DOUBLE)
1995                                 sp [-1].data.f -= sp [0].data.f;
1996                         else {
1997                                 char *p = sp [-1].data.p;
1998                                 p -= GET_NATI (sp [0]);
1999                                 sp [-1].data.p = p;
2000                         }
2001                         BREAK;
2002                 CASE (CEE_MUL)
2003                         ++ip;
2004                         --sp;
2005                         if (sp->type == VAL_I32)
2006                                 sp [-1].data.i *= (gint)GET_NATI (sp [0]);
2007                         else if (sp->type == VAL_I64)
2008                                 sp [-1].data.l *= sp [0].data.l;
2009                         else if (sp->type == VAL_DOUBLE)
2010                                 sp [-1].data.f *= sp [0].data.f;
2011                         BREAK;
2012                 CASE (CEE_DIV)
2013                         ++ip;
2014                         --sp;
2015                         if (sp->type == VAL_I32) {
2016                                 if (GET_NATI (sp [0]) == 0)
2017                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2018                                 sp [-1].data.i /= (gint)GET_NATI (sp [0]);
2019                         } else if (sp->type == VAL_I64) {
2020                                 if (sp [0].data.l == 0)
2021                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2022                                 sp [-1].data.l /= sp [0].data.l;
2023                         } else if (sp->type == VAL_DOUBLE) {
2024                                 /* set NaN is divisor is 0.0 */
2025                                 sp [-1].data.f /= sp [0].data.f;
2026                         }
2027                         BREAK;
2028                 CASE (CEE_DIV_UN)
2029                         ++ip;
2030                         --sp;
2031                         if (sp->type == VAL_I32) {
2032                                 guint32 val;
2033                                 if (GET_NATI (sp [0]) == 0)
2034                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2035                                 val = sp [-1].data.i;
2036                                 val /= (guint32)GET_NATI (sp [0]);
2037                                 sp [-1].data.i = val;
2038                         } else if (sp->type == VAL_I64) {
2039                                 guint64 val;
2040                                 if (sp [0].data.l == 0)
2041                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2042                                 val = sp [-1].data.l;
2043                                 val /= (guint64)sp [0].data.l;
2044                                 sp [-1].data.l = val;
2045                         } else if (sp->type == VAL_NATI) {
2046                                 mono_u val;
2047                                 if (GET_NATI (sp [0]) == 0)
2048                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2049                                 val = (mono_u)sp [-1].data.p;
2050                                 val /= (mono_u)sp [0].data.p;
2051                                 sp [-1].data.p = (gpointer)val;
2052                         }
2053                         BREAK;
2054                 CASE (CEE_REM)
2055                         ++ip;
2056                         --sp;
2057                         if (sp->type == VAL_I32) {
2058                                 if (GET_NATI (sp [0]) == 0)
2059                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2060                                 sp [-1].data.i %= (gint)GET_NATI (sp [0]);
2061                         } else if (sp->type == VAL_I64) {
2062                                 if (sp [0].data.l == 0)
2063                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2064                                 sp [-1].data.l %= sp [0].data.l;
2065                         } else if (sp->type == VAL_DOUBLE) {
2066                                 /* FIXME: what do we actually do here? */
2067                                 sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
2068                         } else {
2069                                 if (GET_NATI (sp [0]) == 0)
2070                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2071                                 (gint)GET_NATI (sp [-1]) %= (gint)GET_NATI (sp [0]);
2072                         }
2073                         BREAK;
2074                 CASE (CEE_REM_UN)
2075                         ++ip;
2076                         --sp;
2077                         if (sp->type == VAL_I32) {
2078                                 if (GET_NATI (sp [0]) == 0)
2079                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2080                                 (guint)sp [-1].data.i %= (guint)GET_NATI (sp [0]);
2081                         } else if (sp->type == VAL_I64) {
2082                                 if (sp [0].data.l == 0)
2083                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2084                                 (guint64)sp [-1].data.l %= (guint64)sp [0].data.l;
2085                         } else if (sp->type == VAL_DOUBLE) {
2086                                 /* unspecified behaviour according to the spec */
2087                         } else {
2088                                 if (GET_NATI (sp [0]) == 0)
2089                                         THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
2090                                 (guint64)GET_NATI (sp [-1]) %= (guint64)GET_NATI (sp [0]);
2091                         }
2092                         BREAK;
2093                 CASE (CEE_AND)
2094                         ++ip;
2095                         --sp;
2096                         if (sp->type == VAL_I32)
2097                                 sp [-1].data.i &= GET_NATI (sp [0]);
2098                         else if (sp->type == VAL_I64)
2099                                 sp [-1].data.l &= sp [0].data.l;
2100                         else
2101                                 GET_NATI (sp [-1]) &= GET_NATI (sp [0]);
2102                         BREAK;
2103                 CASE (CEE_OR)
2104                         ++ip;
2105                         --sp;
2106                         if (sp->type == VAL_I32)
2107                                 sp [-1].data.i |= GET_NATI (sp [0]);
2108                         else if (sp->type == VAL_I64)
2109                                 sp [-1].data.l |= sp [0].data.l;
2110                         else
2111                                 GET_NATI (sp [-1]) |= GET_NATI (sp [0]);
2112                         BREAK;
2113                 CASE (CEE_XOR)
2114                         ++ip;
2115                         --sp;
2116                         if (sp->type == VAL_I32)
2117                                 sp [-1].data.i ^= GET_NATI (sp [0]);
2118                         else if (sp->type == VAL_I64)
2119                                 sp [-1].data.l ^= sp [0].data.l;
2120                         else
2121                                 GET_NATI (sp [-1]) ^= GET_NATI (sp [0]);
2122                         BREAK;
2123                 CASE (CEE_SHL)
2124                         ++ip;
2125                         --sp;
2126                         if (sp [-1].type == VAL_I32)
2127                                 sp [-1].data.i <<= GET_NATI (sp [0]);
2128                         else if (sp [-1].type == VAL_I64)
2129                                 sp [-1].data.l <<= GET_NATI (sp [0]);
2130                         else
2131                                 GET_NATI (sp [-1]) <<= GET_NATI (sp [0]);
2132                         BREAK;
2133                 CASE (CEE_SHR)
2134                         ++ip;
2135                         --sp;
2136                         if (sp [-1].type == VAL_I32)
2137                                 sp [-1].data.i >>= GET_NATI (sp [0]);
2138                         else if (sp [-1].type == VAL_I64)
2139                                 sp [-1].data.l >>= GET_NATI (sp [0]);
2140                         else
2141                                 (gint)GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
2142                         BREAK;
2143                 CASE (CEE_SHR_UN)
2144                         ++ip;
2145                         --sp;
2146                         if (sp [-1].type == VAL_I32)
2147                                 (guint)sp [-1].data.i >>= GET_NATI (sp [0]);
2148                         else if (sp [-1].type == VAL_I64)
2149                                 (guint64)sp [-1].data.l >>= GET_NATI (sp [0]);
2150                         else
2151                                 (guint64)GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
2152                         BREAK;
2153                 CASE (CEE_NEG)
2154                         ++ip;
2155                         --sp;
2156                         if (sp->type == VAL_I32) 
2157                                 sp->data.i = - sp->data.i;
2158                         else if (sp->type == VAL_I64)
2159                                 sp->data.l = - sp->data.l;
2160                         else if (sp->type == VAL_DOUBLE)
2161                                 sp->data.f = - sp->data.f;
2162                         else if (sp->type == VAL_NATI)
2163                                 sp->data.p = (gpointer)(- (mono_i)sp->data.p);
2164                         ++sp;
2165                         BREAK;
2166                 CASE (CEE_NOT)
2167                         ++ip;
2168                         --sp;
2169                         if (sp->type == VAL_I32)
2170                                 sp->data.i = ~ sp->data.i;
2171                         else if (sp->type == VAL_I64)
2172                                 sp->data.l = ~ sp->data.l;
2173                         else if (sp->type == VAL_NATI)
2174                                 sp->data.p = (gpointer)(~ (mono_i)sp->data.p);
2175                         ++sp;
2176                         BREAK;
2177                 CASE (CEE_CONV_U1) /* fall through */
2178                 CASE (CEE_CONV_I1) {
2179                         ++ip;
2180                         switch (sp [-1].type) {
2181                         case VAL_DOUBLE:
2182                                 sp [-1].data.i = (gint8)sp [-1].data.f;
2183                                 break;
2184                         case VAL_I64:
2185                                 sp [-1].data.i = (gint8)sp [-1].data.l;
2186                                 break;
2187                         case VAL_VALUET:
2188                                 ves_abort();
2189                         case VAL_I32:
2190                                 sp [-1].data.i = (gint8)sp [-1].data.i;
2191                                 break;
2192                         default:
2193                                 sp [-1].data.i = (gint8)sp [-1].data.nati;
2194                                 break;
2195                         }
2196                         sp [-1].type = VAL_I32;
2197                         BREAK;
2198                 }
2199                 CASE (CEE_CONV_U2) /* fall through */
2200                 CASE (CEE_CONV_I2) {
2201                         ++ip;
2202                         switch (sp [-1].type) {
2203                         case VAL_DOUBLE:
2204                                 sp [-1].data.i = (gint16)sp [-1].data.f;
2205                                 break;
2206                         case VAL_I64:
2207                                 sp [-1].data.i = (gint16)sp [-1].data.l;
2208                                 break;
2209                         case VAL_VALUET:
2210                                 ves_abort();
2211                         case VAL_I32:
2212                                 sp [-1].data.i = (gint16)sp [-1].data.i;
2213                                 break;
2214                         default:
2215                                 sp [-1].data.i = (gint16)sp [-1].data.nati;
2216                                 break;
2217                         }
2218                         sp [-1].type = VAL_I32;
2219                         BREAK;
2220                 }
2221                 CASE (CEE_CONV_U4) /* Fall through */
2222 #if SIZEOF_VOID_P == 4
2223                 CASE (CEE_CONV_I) /* Fall through */
2224                 CASE (CEE_CONV_U) /* Fall through */
2225 #endif
2226                 CASE (CEE_CONV_I4) {
2227                         ++ip;
2228                         switch (sp [-1].type) {
2229                         case VAL_DOUBLE:
2230                                 sp [-1].data.i = (gint32)sp [-1].data.f;
2231                                 break;
2232                         case VAL_I64:
2233                                 sp [-1].data.i = (gint32)sp [-1].data.l;
2234                                 break;
2235                         case VAL_VALUET:
2236                                 ves_abort();
2237                         case VAL_I32:
2238                                 break;
2239                         default:
2240                                 sp [-1].data.i = (gint32)sp [-1].data.p;
2241                                 break;
2242                         }
2243                         sp [-1].type = VAL_I32;
2244                         BREAK;
2245                 }
2246 #if SIZEOF_VOID_P == 8
2247                 CASE (CEE_CONV_I) /* Fall through */
2248 #endif
2249                 CASE (CEE_CONV_I8)
2250                         ++ip;
2251                         switch (sp [-1].type) {
2252                         case VAL_DOUBLE:
2253                                 sp [-1].data.l = (gint64)sp [-1].data.f;
2254                                 break;
2255                         case VAL_I64:
2256                                 break;
2257                         case VAL_VALUET:
2258                                 ves_abort();
2259                         case VAL_I32:
2260                                 sp [-1].data.l = (gint64)sp [-1].data.i;
2261                                 break;
2262                         default:
2263                                 sp [-1].data.l = (gint64)sp [-1].data.nati;
2264                                 break;
2265                         }
2266                         sp [-1].type = VAL_I64;
2267                         BREAK;
2268                 CASE (CEE_CONV_R4) /* Fall through */
2269                 CASE (CEE_CONV_R8) {
2270                         ++ip;
2271                         switch (sp [-1].type) {
2272                         case VAL_DOUBLE:
2273                                 sp [-1].data.f = (double)sp [-1].data.f;
2274                                 break;
2275                         case VAL_I64:
2276                                 sp [-1].data.f = (double)sp [-1].data.l;
2277                                 break;
2278                         case VAL_VALUET:
2279                                 ves_abort();
2280                         case VAL_I32:
2281                                 sp [-1].data.f = (double)sp [-1].data.i;
2282                                 break;
2283                         default:
2284                                 sp [-1].data.f = (double)sp [-1].data.nati;
2285                                 break;
2286                         }
2287                         sp [-1].type = VAL_DOUBLE;
2288                         BREAK;
2289                 }
2290 #if SIZEOF_VOID_P == 8
2291                 CASE (CEE_CONV_U) /* Fall through */
2292 #endif
2293                 CASE (CEE_CONV_U8)
2294                         ++ip;
2295
2296                         switch (sp [-1].type){
2297                         case VAL_DOUBLE:
2298                                 sp [-1].data.l = (guint64)sp [-1].data.f;
2299                                 break;
2300                         case VAL_I64:
2301                                 break;
2302                         case VAL_VALUET:
2303                                 ves_abort();
2304                         case VAL_I32:
2305                                 sp [-1].data.l = (guint64) sp [-1].data.i;
2306                                 break;
2307                         default:
2308                                 sp [-1].data.l = (guint64) sp [-1].data.nati;
2309                                 break;
2310                         }
2311                         sp [-1].type = VAL_I64;
2312                         BREAK;
2313                 CASE (CEE_CPOBJ) {
2314                         MonoClass *vtklass;
2315                         ++ip;
2316                         vtklass = mono_class_get (image, read32 (ip));
2317                         ip += 4;
2318                         sp -= 2;
2319                         memcpy (sp [0].data.p, sp [1].data.p, mono_class_value_size (vtklass, NULL));
2320                         BREAK;
2321                 }
2322                 CASE (CEE_LDOBJ) {
2323                         guint32 token;
2324                         MonoClass *c;
2325                         char *addr;
2326
2327                         ++ip;
2328                         token = read32 (ip);
2329                         ip += 4;
2330                         c = mono_class_get (image, token);
2331                         addr = sp [-1].data.vt.vt;
2332                         vt_alloc (&c->byval_arg, &sp [-1]);
2333                         stackval_from_data (&c->byval_arg, &sp [-1], addr);
2334                         BREAK;
2335                 }
2336                 CASE (CEE_LDSTR) {
2337                         MonoObject *o;
2338                         guint32 str_index;
2339
2340                         ip++;
2341                         str_index = mono_metadata_token_index (read32 (ip));
2342                         ip += 4;
2343
2344                         o = (MonoObject*)mono_ldstr (domain, image, str_index);
2345                         sp->type = VAL_OBJ;
2346                         sp->data.p = o;
2347                         sp->data.vt.klass = NULL;
2348
2349                         ++sp;
2350                         BREAK;
2351                 }
2352                 CASE (CEE_NEWOBJ) {
2353                         MonoObject *o;
2354                         MonoClass *newobj_class;
2355                         MonoMethodSignature *csig;
2356                         stackval valuetype_this;
2357                         stackval *endsp = sp;
2358                         guint32 token;
2359                         stackval retval;
2360
2361                         frame->ip = ip;
2362
2363                         ip++;
2364                         token = read32 (ip);
2365                         ip += 4;
2366
2367                         if (!(child_frame.method = mono_get_method (image, token, NULL)))
2368                                 THROW_EX (mono_get_exception_missing_method (), ip -5);
2369
2370                         csig = child_frame.method->signature;
2371                         newobj_class = child_frame.method->klass;
2372                         /*if (profiling_classes) {
2373                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
2374                                 count++;
2375                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
2376                         }*/
2377                                 
2378
2379                         if (newobj_class->parent == mono_defaults.array_class) {
2380                                 sp -= csig->param_count;
2381                                 o = ves_array_create (domain, newobj_class, csig, sp);
2382                                 goto array_constructed;
2383                         }
2384
2385                         /*
2386                          * First arg is the object.
2387                          */
2388                         if (newobj_class->valuetype) {
2389                                 void *zero;
2390                                 vt_alloc (&newobj_class->byval_arg, &valuetype_this);
2391                                 if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
2392                                         zero = valuetype_this.data.vt.vt;
2393                                         child_frame.obj = valuetype_this.data.vt.vt;
2394                                 } else {
2395                                         memset (&valuetype_this, 0, sizeof (stackval));
2396                                         zero = &valuetype_this;
2397                                         child_frame.obj = &valuetype_this;
2398                                 }
2399                                 stackval_from_data (&newobj_class->byval_arg, &valuetype_this, zero);
2400                         } else {
2401                                 if (newobj_class != mono_defaults.string_class) {
2402                                         o = mono_object_new (domain, newobj_class);
2403                                         child_frame.obj = o;
2404                                 } else {
2405                                         child_frame.retval = &retval;
2406                                 }
2407                         }
2408
2409                         if (csig->param_count) {
2410                                 sp -= csig->param_count;
2411                                 child_frame.stack_args = sp;
2412                         } else {
2413                                 child_frame.stack_args = NULL;
2414                         }
2415
2416                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2417
2418                         child_frame.ex = NULL;
2419                         child_frame.ex_handler = NULL;
2420
2421                         ves_exec_method (&child_frame);
2422
2423                         while (endsp > sp) {
2424                                 --endsp;
2425                                 vt_free (endsp);
2426                         }
2427
2428                         if (child_frame.ex) {
2429                                 /*
2430                                  * An exception occurred, need to run finally, fault and catch handlers..
2431                                  */
2432                                 frame->ex = child_frame.ex;
2433                                 goto handle_finally;
2434                         }
2435                         /*
2436                          * a constructor returns void, but we need to return the object we created
2437                          */
2438 array_constructed:
2439                         if (newobj_class->valuetype && !newobj_class->enumtype) {
2440                                 *sp = valuetype_this;
2441                         } else if (newobj_class == mono_defaults.string_class) {
2442                                 *sp = retval;
2443                         } else {
2444                                 sp->type = VAL_OBJ;
2445                                 sp->data.p = o;
2446                                 sp->data.vt.klass = newobj_class;
2447                         }
2448                         ++sp;
2449                         BREAK;
2450                 }
2451                 CASE (CEE_CASTCLASS) /* Fall through */
2452                 CASE (CEE_ISINST) {
2453                         MonoObject *o;
2454                         MonoVTable *vt;
2455                         MonoClass *c , *oclass;
2456                         guint32 token;
2457                         int do_isinst = *ip == CEE_ISINST;
2458                         gboolean found = FALSE;
2459
2460                         ++ip;
2461                         token = read32 (ip);
2462                         c = mono_class_get (image, token);
2463
2464                         g_assert (sp [-1].type == VAL_OBJ);
2465
2466                         if ((o = sp [-1].data.p)) {
2467
2468                                 vt = o->vtable;
2469                                 oclass = vt->klass;
2470
2471                                 if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
2472                                         if ((c->interface_id <= oclass->max_interface_id) &&
2473                                             vt->interface_offsets [c->interface_id])
2474                                                 found = TRUE;
2475                                 } else {
2476                                         if (oclass == mono_defaults.transparent_proxy_class) {
2477                                                 /* fixme: add check for IRemotingTypeInfo */
2478                                                 MonoRealProxy *rp = ((MonoTransparentProxy *)o)->rp;
2479                                                 MonoType *type;
2480                                                 type = rp->class_to_proxy->type;
2481                                                 oclass = mono_class_from_mono_type (type);
2482                                         }
2483                                         /* handle array casts */
2484                                         if (oclass->rank && oclass->rank == c->rank) {
2485                                                 if ((oclass->element_class->baseval - c->element_class->baseval) <= c->element_class->diffval) {
2486                                                         sp [-1].data.vt.klass = c;
2487                                                         found = TRUE;
2488                                                 }
2489                                         } else if ((oclass->baseval - c->baseval) <= c->diffval) {
2490                                                 sp [-1].data.vt.klass = c;
2491                                                 found = TRUE;
2492                                         }
2493                                 }
2494
2495                                 if (!found) {
2496                                         if (do_isinst) {
2497                                                 sp [-1].data.p = NULL;
2498                                                 sp [-1].data.vt.klass = NULL;
2499                                         } else
2500                                                 THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
2501                                 }
2502                         }
2503                         ip += 4;
2504                         BREAK;
2505                 }
2506                 CASE (CEE_CONV_R_UN)
2507                         switch (sp [-1].type) {
2508                         case VAL_DOUBLE:
2509                                 break;
2510                         case VAL_I64:
2511                                 sp [-1].data.f = (double)(guint64)sp [-1].data.l;
2512                                 break;
2513                         case VAL_VALUET:
2514                                 ves_abort();
2515                         case VAL_I32:
2516                                 sp [-1].data.f = (double)(guint32)sp [-1].data.i;
2517                                 break;
2518                         default:
2519                                 sp [-1].data.f = (double)(guint64)sp [-1].data.nati;
2520                                 break;
2521                         }
2522                         sp [-1].type = VAL_DOUBLE;
2523                         BREAK;
2524                 CASE (CEE_UNUSED58)
2525                 CASE (CEE_UNUSED1) ves_abort(); BREAK;
2526                 CASE (CEE_UNBOX) {
2527                         MonoObject *o;
2528                         MonoClass *c;
2529                         guint32 token;
2530
2531                         ++ip;
2532                         token = read32 (ip);
2533                         
2534                         c = mono_class_get (image, token);
2535                         
2536                         o = sp [-1].data.p;
2537                         if (!o)
2538                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
2539
2540                         if (o->vtable->klass->element_class->type_token != c->element_class->type_token)
2541                                 THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
2542
2543                         sp [-1].type = VAL_MP;
2544                         sp [-1].data.p = (char *)o + sizeof (MonoObject);
2545
2546                         ip += 4;
2547                         BREAK;
2548                 }
2549                 CASE (CEE_THROW)
2550                         --sp;
2551                         frame->ex_handler = NULL;
2552                         THROW_EX (sp->data.p, ip);
2553                         BREAK;
2554                 CASE (CEE_LDFLDA) /* Fall through */
2555                 CASE (CEE_LDFLD) {
2556                         MonoObject *obj;
2557                         MonoClassField *field;
2558                         guint32 token, offset;
2559                         int load_addr = *ip == CEE_LDFLDA;
2560
2561                         if (!sp [-1].data.p)
2562                                 THROW_EX (mono_get_exception_null_reference (), ip);
2563                         
2564                         ++ip;
2565                         token = read32 (ip);
2566                         ip += 4;
2567
2568                         if (sp [-1].type == VAL_OBJ) {
2569                                 obj = sp [-1].data.p;
2570                                 /* if we access a field from our parent and the parent was 
2571                                  * defined in another assembly, we get a memberref.
2572                                  */
2573                                 if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
2574                                         field = mono_field_from_memberref (image, token, NULL);
2575                                 else
2576                                         field = mono_class_get_field (obj->vtable->klass, token);
2577                                 offset = field->offset;
2578                         } else { /* valuetype */
2579                                 /*g_assert (sp [-1].type == VAL_VALUETA); */
2580                                 obj = sp [-1].data.vt.vt;
2581                                 field = mono_class_get_field (sp [-1].data.vt.klass, token);
2582                                 offset = field->offset - sizeof (MonoObject);
2583                         }
2584                         if (load_addr) {
2585                                 sp [-1].type = VAL_TP;
2586                                 sp [-1].data.p = (char*)obj + offset;
2587                                 sp [-1].data.vt.klass = mono_class_from_mono_type (field->type);
2588                         } else {
2589                                 vt_alloc (field->type, &sp [-1]);
2590                                 stackval_from_data (field->type, &sp [-1], (char*)obj + offset);
2591                                 
2592                         }
2593                         BREAK;
2594                 }
2595                 CASE (CEE_STFLD) {
2596                         MonoObject *obj;
2597                         MonoClassField *field;
2598                         guint32 token, offset;
2599
2600                         sp -= 2;
2601                         
2602                         if (!sp [0].data.p)
2603                                 THROW_EX (mono_get_exception_null_reference (), ip);
2604                         
2605                         ++ip;
2606                         token = read32 (ip);
2607                         ip += 4;
2608                         
2609                         if (sp [0].type == VAL_OBJ) {
2610                                 obj = sp [0].data.p;
2611                                 /* if we access a field from our parent and the parent was 
2612                                  * defined in another assembly, we get a memberref.
2613                                  */
2614                                 if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
2615                                         field = mono_field_from_memberref (image, token, NULL);
2616                                 else
2617                                         field = mono_class_get_field (obj->vtable->klass, token);
2618                                 offset = field->offset;
2619                         } else { /* valuetype */
2620                                 /*g_assert (sp->type == VAL_VALUETA); */
2621                                 obj = sp [0].data.vt.vt;
2622                                 field = mono_class_get_field (sp [0].data.vt.klass, token);
2623                                 offset = field->offset - sizeof (MonoObject);
2624                         }
2625
2626                         stackval_to_data (field->type, &sp [1], (char*)obj + offset);
2627                         vt_free (&sp [1]);
2628                         BREAK;
2629                 }
2630                 CASE (CEE_LDSFLD) /* Fall through */
2631                 CASE (CEE_LDSFLDA) {
2632                         MonoVTable *vt;
2633                         MonoClass *klass;
2634                         MonoClassField *field;
2635                         guint32 token;
2636                         int load_addr = *ip == CEE_LDSFLDA;
2637                         gpointer addr;
2638
2639                         ++ip;
2640                         token = read32 (ip);
2641                         ip += 4;
2642                         
2643                         /* need to handle fieldrefs */
2644                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
2645                                 field = mono_field_from_memberref (image, token, &klass);
2646                         } else {
2647                                 klass = mono_class_get (image, 
2648                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
2649                                 field = mono_class_get_field (klass, token);
2650                         }
2651                         g_assert (field);
2652                         
2653                         vt = mono_class_vtable (domain, klass);
2654                         addr = (char*)(vt->data) + field->offset;
2655
2656                         if (load_addr) {
2657                                 sp->type = VAL_TP;
2658                                 sp->data.p = addr;
2659                                 sp->data.vt.klass = mono_class_from_mono_type (field->type);
2660                         } else {
2661                                 vt_alloc (field->type, sp);
2662                                 stackval_from_data (field->type, sp, addr);
2663                         }
2664                         ++sp;
2665                         BREAK;
2666                 }
2667                 CASE (CEE_STSFLD) {
2668                         MonoVTable *vt;
2669                         MonoClass *klass;
2670                         MonoClassField *field;
2671                         guint32 token;
2672                         gpointer addr;
2673
2674                         ++ip;
2675                         token = read32 (ip);
2676                         ip += 4;
2677                         --sp;
2678
2679                         /* need to handle fieldrefs */
2680                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
2681                                 field = mono_field_from_memberref (image, token, &klass);
2682                         } else {
2683                                 klass = mono_class_get (image, 
2684                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
2685                                 field = mono_class_get_field (klass, token);
2686                         }
2687                         g_assert (field);
2688
2689                         vt = mono_class_vtable (domain, klass);
2690                         addr = (char*)(vt->data) + field->offset;
2691
2692                         stackval_to_data (field->type, sp, addr);
2693                         vt_free (sp);
2694                         BREAK;
2695                 }
2696                 CASE (CEE_STOBJ) {
2697                         MonoClass *vtklass;
2698                         ++ip;
2699                         vtklass = mono_class_get (image, read32 (ip));
2700                         ip += 4;
2701                         sp -= 2;
2702                         memcpy (sp [0].data.p, sp [1].data.vt.vt, mono_class_value_size (vtklass, NULL));
2703                         BREAK;
2704                 }
2705 #if SIZEOF_VOID_P == 8
2706                 CASE (CEE_CONV_OVF_I_UN)
2707 #endif
2708                 CASE (CEE_CONV_OVF_I8_UN) {
2709                         switch (sp [-1].type) {
2710                         case VAL_DOUBLE:
2711                                 if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807L)
2712                                         THROW_EX (mono_get_exception_overflow (), ip);
2713                                 sp [-1].data.l = (guint64)sp [-1].data.f;
2714                                 break;
2715                         case VAL_I64:
2716                                 if (sp [-1].data.l < 0)
2717                                         THROW_EX (mono_get_exception_overflow (), ip);
2718                                 break;
2719                         case VAL_VALUET:
2720                                 ves_abort();
2721                         case VAL_I32:
2722                                 /* Can't overflow */
2723                                 sp [-1].data.l = (guint64)sp [-1].data.i;
2724                                 break;
2725                         default:
2726                                 if ((gint64)sp [-1].data.nati < 0)
2727                                         THROW_EX (mono_get_exception_overflow (), ip);
2728                                 sp [-1].data.l = (guint64)sp [-1].data.nati;
2729                                 break;
2730                         }
2731                         sp [-1].type = VAL_I64;
2732                         ++ip;
2733                         BREAK;
2734                 }
2735 #if SIZEOF_VOID_P == 8
2736                 CASE (CEE_CONV_OVF_U_UN) 
2737 #endif
2738                 CASE (CEE_CONV_OVF_U8_UN) {
2739                         switch (sp [-1].type) {
2740                         case VAL_DOUBLE:
2741                                 if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT64_MAX)
2742                                         THROW_EX (mono_get_exception_overflow (), ip);
2743                                 sp [-1].data.l = (guint64)sp [-1].data.f;
2744                                 break;
2745                         case VAL_I64:
2746                                 /* nothing to do */
2747                                 break;
2748                         case VAL_VALUET:
2749                                 ves_abort();
2750                         case VAL_I32:
2751                                 /* Can't overflow */
2752                                 sp [-1].data.l = (guint64)sp [-1].data.i;
2753                                 break;
2754                         default:
2755                                 /* Can't overflow */
2756                                 sp [-1].data.l = (guint64)sp [-1].data.nati;
2757                                 break;
2758                         }
2759                         sp [-1].type = VAL_I64;
2760                         ++ip;
2761                         BREAK;
2762                 }
2763 #if SIZEOF_VOID_P == 4
2764                 CASE (CEE_CONV_OVF_I_UN)
2765                 CASE (CEE_CONV_OVF_U_UN) 
2766 #endif
2767                 CASE (CEE_CONV_OVF_I1_UN)
2768                 CASE (CEE_CONV_OVF_I2_UN)
2769                 CASE (CEE_CONV_OVF_I4_UN)
2770                 CASE (CEE_CONV_OVF_U1_UN)
2771                 CASE (CEE_CONV_OVF_U2_UN)
2772                 CASE (CEE_CONV_OVF_U4_UN) {
2773                         guint64 value;
2774                         switch (sp [-1].type) {
2775                         case VAL_DOUBLE:
2776                                 value = (guint64)sp [-1].data.f;
2777                                 break;
2778                         case VAL_I64:
2779                                 value = (guint64)sp [-1].data.l;
2780                                 break;
2781                         case VAL_VALUET:
2782                                 ves_abort();
2783                         case VAL_I32:
2784                                 value = (guint64)sp [-1].data.i;
2785                                 break;
2786                         default:
2787                                 value = (guint64)sp [-1].data.nati;
2788                                 break;
2789                         }
2790                         switch (*ip) {
2791                         case CEE_CONV_OVF_I1_UN:
2792                                 if (value > 127)
2793                                         THROW_EX (mono_get_exception_overflow (), ip);
2794                                 sp [-1].data.i = value;
2795                                 sp [-1].type = VAL_I32;
2796                                 break;
2797                         case CEE_CONV_OVF_I2_UN:
2798                                 if (value > 32767)
2799                                         THROW_EX (mono_get_exception_overflow (), ip);
2800                                 sp [-1].data.i = value;
2801                                 sp [-1].type = VAL_I32;
2802                                 break;
2803 #if SIZEOF_VOID_P == 4
2804                         case CEE_CONV_OVF_I_UN: /* Fall through */
2805 #endif
2806                         case CEE_CONV_OVF_I4_UN:
2807                                 if (value > 2147483647)
2808                                         THROW_EX (mono_get_exception_overflow (), ip);
2809                                 sp [-1].data.i = value;
2810                                 sp [-1].type = VAL_I32;
2811                                 break;
2812                         case CEE_CONV_OVF_U1_UN:
2813                                 if (value > 255)
2814                                         THROW_EX (mono_get_exception_overflow (), ip);
2815                                 sp [-1].data.i = value;
2816                                 sp [-1].type = VAL_I32;
2817                                 break;
2818                         case CEE_CONV_OVF_U2_UN:
2819                                 if (value > 65535)
2820                                         THROW_EX (mono_get_exception_overflow (), ip);
2821                                 sp [-1].data.i = value;
2822                                 sp [-1].type = VAL_I32;
2823                                 break;
2824 #if SIZEOF_VOID_P == 4
2825                         case CEE_CONV_OVF_U_UN: /* Fall through */
2826 #endif
2827                         case CEE_CONV_OVF_U4_UN:
2828                                 if (value > 4294967295U)
2829                                         THROW_EX (mono_get_exception_overflow (), ip);
2830                                 sp [-1].data.i = value;
2831                                 sp [-1].type = VAL_I32;
2832                                 break;
2833                         default:
2834                                 g_assert_not_reached ();
2835                         }
2836                         ++ip;
2837                         BREAK;
2838                 }
2839                 CASE (CEE_BOX) {
2840                         guint32 token;
2841                         MonoClass *class;
2842
2843                         ip++;
2844                         token = read32 (ip);
2845
2846                         class = mono_class_get (image, token);
2847                         g_assert (class != NULL);
2848
2849                         sp [-1].type = VAL_OBJ;
2850                         if (class->byval_arg.type == MONO_TYPE_VALUETYPE && !class->enumtype) 
2851                                 sp [-1].data.p = mono_value_box (domain, class, sp [-1].data.p);
2852                         else
2853                                 sp [-1].data.p = mono_value_box (domain, class, &sp [-1]);
2854                         /* need to vt_free (sp); */
2855
2856                         ip += 4;
2857
2858                         BREAK;
2859                 }
2860                 CASE (CEE_NEWARR) {
2861                         MonoClass *class;
2862                         MonoObject *o;
2863                         guint32 token;
2864
2865                         ip++;
2866                         token = read32 (ip);
2867                         class = mono_class_get (image, token);
2868                         o = (MonoObject*) mono_array_new (domain, class, sp [-1].data.i);
2869                         ip += 4;
2870
2871                         sp [-1].type = VAL_OBJ;
2872                         sp [-1].data.p = o;
2873                         /*if (profiling_classes) {
2874                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
2875                                 count++;
2876                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
2877                         }*/
2878
2879                         BREAK;
2880                 }
2881                 CASE (CEE_LDLEN) {
2882                         MonoArray *o;
2883
2884                         ip++;
2885
2886                         g_assert (sp [-1].type == VAL_OBJ);
2887
2888                         o = sp [-1].data.p;
2889                         if (!o)
2890                                 THROW_EX (mono_get_exception_null_reference (), ip - 1);
2891                         
2892                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
2893
2894                         sp [-1].type = VAL_I32;
2895                         sp [-1].data.i = mono_array_length (o);
2896
2897                         BREAK;
2898                 }
2899                 CASE (CEE_LDELEMA) {
2900                         MonoArray *o;
2901                         guint32 esize, token;
2902                         
2903                         ++ip;
2904                         token = read32 (ip);
2905                         ip += 4;
2906                         sp -= 2;
2907
2908                         g_assert (sp [0].type == VAL_OBJ);
2909                         o = sp [0].data.p;
2910
2911                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
2912                         
2913                         if (sp [1].data.nati >= mono_array_length (o))
2914                                 THROW_EX (mono_get_exception_index_out_of_range (), ip - 5);
2915
2916                         /* check the array element corresponds to token */
2917                         esize = mono_array_element_size (o->obj.vtable->klass);
2918                         
2919                         sp->type = VAL_MP;
2920                         sp->data.p = mono_array_addr_with_size (o, esize, sp [1].data.i);
2921                         sp->data.vt.klass = o->obj.vtable->klass->element_class;
2922
2923                         ++sp;
2924                         BREAK;
2925                 }
2926                 CASE (CEE_LDELEM_I1) /* fall through */
2927                 CASE (CEE_LDELEM_U1) /* fall through */
2928                 CASE (CEE_LDELEM_I2) /* fall through */
2929                 CASE (CEE_LDELEM_U2) /* fall through */
2930                 CASE (CEE_LDELEM_I4) /* fall through */
2931                 CASE (CEE_LDELEM_U4) /* fall through */
2932                 CASE (CEE_LDELEM_I8)  /* fall through */
2933                 CASE (CEE_LDELEM_I)  /* fall through */
2934                 CASE (CEE_LDELEM_R4) /* fall through */
2935                 CASE (CEE_LDELEM_R8) /* fall through */
2936                 CASE (CEE_LDELEM_REF) {
2937                         MonoArray *o;
2938                         mono_u aindex;
2939
2940                         sp -= 2;
2941
2942                         g_assert (sp [0].type == VAL_OBJ);
2943                         o = sp [0].data.p;
2944                         if (!o)
2945                                 THROW_EX (mono_get_exception_null_reference (), ip);
2946
2947                         g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
2948                         
2949                         aindex = sp [1].data.nati;
2950                         if (aindex >= mono_array_length (o))
2951                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
2952                 
2953                         /*
2954                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
2955                          */
2956                         switch (*ip) {
2957                         case CEE_LDELEM_I1:
2958                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
2959                                 sp [0].type = VAL_I32;
2960                                 break;
2961                         case CEE_LDELEM_U1:
2962                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
2963                                 sp [0].type = VAL_I32;
2964                                 break;
2965                         case CEE_LDELEM_I2:
2966                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
2967                                 sp [0].type = VAL_I32;
2968                                 break;
2969                         case CEE_LDELEM_U2:
2970                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
2971                                 sp [0].type = VAL_I32;
2972                                 break;
2973                         case CEE_LDELEM_I:
2974                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
2975                                 sp [0].type = VAL_NATI;
2976                                 break;
2977                         case CEE_LDELEM_I4:
2978                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
2979                                 sp [0].type = VAL_I32;
2980                                 break;
2981                         case CEE_LDELEM_U4:
2982                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
2983                                 sp [0].type = VAL_I32;
2984                                 break;
2985                         case CEE_LDELEM_I8:
2986                                 sp [0].data.l = mono_array_get (o, gint64, aindex);
2987                                 sp [0].type = VAL_I64;
2988                                 break;
2989                         case CEE_LDELEM_R4:
2990                                 sp [0].data.f = mono_array_get (o, float, aindex);
2991                                 sp [0].type = VAL_DOUBLE;
2992                                 break;
2993                         case CEE_LDELEM_R8:
2994                                 sp [0].data.f = mono_array_get (o, double, aindex);
2995                                 sp [0].type = VAL_DOUBLE;
2996                                 break;
2997                         case CEE_LDELEM_REF:
2998                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
2999                                 sp [0].data.vt.klass = NULL;
3000                                 sp [0].type = VAL_OBJ;
3001                                 break;
3002                         default:
3003                                 ves_abort();
3004                         }
3005
3006                         ++ip;
3007                         ++sp;
3008                         BREAK;
3009                 }
3010                 CASE (CEE_STELEM_I)  /* fall through */
3011                 CASE (CEE_STELEM_I1) /* fall through */ 
3012                 CASE (CEE_STELEM_I2) /* fall through */
3013                 CASE (CEE_STELEM_I4) /* fall through */
3014                 CASE (CEE_STELEM_I8) /* fall through */
3015                 CASE (CEE_STELEM_R4) /* fall through */
3016                 CASE (CEE_STELEM_R8) /* fall through */
3017                 CASE (CEE_STELEM_REF) {
3018                         MonoArray *o;
3019                         MonoClass *ac;
3020                         mono_u aindex;
3021
3022                         sp -= 3;
3023
3024                         g_assert (sp [0].type == VAL_OBJ);
3025                         o = sp [0].data.p;
3026                         if (!o)
3027                                 THROW_EX (mono_get_exception_null_reference (), ip);
3028
3029                         ac = o->obj.vtable->klass;
3030                         g_assert (MONO_CLASS_IS_ARRAY (ac));
3031                     
3032                         aindex = sp [1].data.nati;
3033                         if (aindex >= mono_array_length (o))
3034                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3035
3036                         /*
3037                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3038                          */
3039                         switch (*ip) {
3040                         case CEE_STELEM_I:
3041                                 mono_array_set (o, mono_i, aindex, sp [2].data.nati);
3042                                 break;
3043                         case CEE_STELEM_I1:
3044                                 mono_array_set (o, gint8, aindex, sp [2].data.i);
3045                                 break;
3046                         case CEE_STELEM_I2:
3047                                 mono_array_set (o, gint16, aindex, sp [2].data.i);
3048                                 break;
3049                         case CEE_STELEM_I4:
3050                                 mono_array_set (o, gint32, aindex, sp [2].data.i);
3051                                 break;
3052                         case CEE_STELEM_I8:
3053                                 mono_array_set (o, gint64, aindex, sp [2].data.l);
3054                                 break;
3055                         case CEE_STELEM_R4:
3056                                 mono_array_set (o, float, aindex, sp [2].data.f);
3057                                 break;
3058                         case CEE_STELEM_R8:
3059                                 mono_array_set (o, double, aindex, sp [2].data.f);
3060                                 break;
3061                         case CEE_STELEM_REF:
3062                                 g_assert (sp [2].type == VAL_OBJ);
3063                                 mono_array_set (o, gpointer, aindex, sp [2].data.p);
3064                                 break;
3065                         default:
3066                                 ves_abort();
3067                         }
3068
3069                         ++ip;
3070                         BREAK;
3071                 }
3072                 CASE (CEE_UNUSED2) 
3073                 CASE (CEE_UNUSED3) 
3074                 CASE (CEE_UNUSED4) 
3075                 CASE (CEE_UNUSED5) 
3076                 CASE (CEE_UNUSED6) 
3077                 CASE (CEE_UNUSED7) 
3078                 CASE (CEE_UNUSED8) 
3079                 CASE (CEE_UNUSED9) 
3080                 CASE (CEE_UNUSED10) 
3081                 CASE (CEE_UNUSED11) 
3082                 CASE (CEE_UNUSED12) 
3083                 CASE (CEE_UNUSED13) 
3084                 CASE (CEE_UNUSED14) 
3085                 CASE (CEE_UNUSED15) 
3086                 CASE (CEE_UNUSED16) 
3087                 CASE (CEE_UNUSED17) ves_abort(); BREAK;
3088                 CASE (CEE_CONV_OVF_I1)
3089                         if (sp [-1].type == VAL_I32) {
3090                                 if (sp [-1].data.i < 128 || sp [-1].data.i > 127)
3091                                         THROW_EX (mono_get_exception_overflow (), ip);
3092                                 sp [-1].data.i = (gint8)sp [-1].data.i;
3093                         } else if (sp [-1].type == VAL_I64) {
3094                                 if (sp [-1].data.l < 128 || sp [-1].data.l > 127)
3095                                         THROW_EX (mono_get_exception_overflow (), ip);
3096                                 sp [-1].data.i = (gint8)sp [-1].data.l;
3097                         } else {
3098                                 ves_abort();
3099                         }
3100                         ++ip;
3101                         BREAK;
3102                 CASE (CEE_CONV_OVF_U1)
3103                         if (sp [-1].type == VAL_I32) {
3104                                 if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
3105                                         THROW_EX (mono_get_exception_overflow (), ip);
3106                                 sp [-1].data.i = (gint8)sp [-1].data.i;
3107                         } else if (sp [-1].type == VAL_I64) {
3108                                 if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
3109                                         THROW_EX (mono_get_exception_overflow (), ip);
3110                                 sp [-1].data.i = (gint8)sp [-1].data.l;
3111                         } else {
3112                                 ves_abort();
3113                         }
3114                         ++ip;
3115                         BREAK;
3116                 CASE (CEE_CONV_OVF_I2)
3117                 CASE (CEE_CONV_OVF_U2)
3118                         ++ip;
3119                         /* FIXME: handle other cases */
3120                         if (sp [-1].type == VAL_I32) {
3121                                 /* defined as NOP */
3122                         } else {
3123                                 ves_abort();
3124                         }
3125                         BREAK;
3126                 CASE (CEE_CONV_OVF_I4)
3127                         /* FIXME: handle other cases */
3128                         if (sp [-1].type == VAL_I32) {
3129                                 /* defined as NOP */
3130                         } else if(sp [-1].type == VAL_I64) {
3131                                 sp [-1].data.i = (gint32)sp [-1].data.l;
3132                                 sp [-1].type = VAL_I32;
3133                         } else {
3134                                 ves_abort();
3135                         }
3136                         ++ip;
3137                         BREAK;
3138                 CASE (CEE_CONV_OVF_U4)
3139                         /* FIXME: handle other cases */
3140                         if (sp [-1].type == VAL_I32) {
3141                                 /* defined as NOP */
3142                         } else if(sp [-1].type == VAL_I64) {
3143                                 sp [-1].data.i = (guint32)sp [-1].data.l;
3144                                 sp [-1].type = VAL_I32;
3145                         } else {
3146                                 ves_abort();
3147                         }
3148                         ++ip;
3149                         BREAK;
3150                 CASE (CEE_CONV_OVF_I8)
3151                         /* FIXME: handle other cases */
3152                         if (sp [-1].type == VAL_I32) {
3153                                 sp [-1].data.l = (guint64)sp [-1].data.l;
3154                                 sp [-1].type = VAL_I64;
3155                         } else if(sp [-1].type == VAL_I64) {
3156                                 /* defined as NOP */
3157                         } else {
3158                                 ves_abort();
3159                         }
3160                         ++ip;
3161                         BREAK;
3162                 CASE (CEE_CONV_OVF_U8)
3163                         /* FIXME: handle other cases */
3164                         if (sp [-1].type == VAL_I32) {
3165                                 sp [-1].data.l = (guint64) sp [-1].data.i;
3166                                 sp [-1].type = VAL_I64;
3167                         } else if(sp [-1].type == VAL_I64) {
3168                                 /* defined as NOP */
3169                         } else {
3170                                 ves_abort();
3171                         }
3172                         ++ip;
3173                         BREAK;
3174                 CASE (CEE_UNUSED50) 
3175                 CASE (CEE_UNUSED18) 
3176                 CASE (CEE_UNUSED19) 
3177                 CASE (CEE_UNUSED20) 
3178                 CASE (CEE_UNUSED21) 
3179                 CASE (CEE_UNUSED22) 
3180                 CASE (CEE_UNUSED23) ves_abort(); BREAK;
3181                 CASE (CEE_REFANYVAL) ves_abort(); BREAK;
3182                 CASE (CEE_CKFINITE)
3183                         if (!finite(sp [-1].data.f))
3184                                 THROW_EX (mono_get_exception_arithmetic (), ip);
3185                         ++ip;
3186                         BREAK;
3187                 CASE (CEE_UNUSED24) ves_abort(); BREAK;
3188                 CASE (CEE_UNUSED25) ves_abort(); BREAK;
3189                 CASE (CEE_MKREFANY) ves_abort(); BREAK;
3190                 CASE (CEE_UNUSED59) 
3191                 CASE (CEE_UNUSED60) 
3192                 CASE (CEE_UNUSED61) 
3193                 CASE (CEE_UNUSED62) 
3194                 CASE (CEE_UNUSED63) 
3195                 CASE (CEE_UNUSED64) 
3196                 CASE (CEE_UNUSED65) 
3197                 CASE (CEE_UNUSED66) 
3198                 CASE (CEE_UNUSED67) ves_abort(); BREAK;
3199                 CASE (CEE_LDTOKEN) {
3200                         gpointer handle;
3201                         MonoClass *handle_class;
3202                         ++ip;
3203                         handle = mono_ldtoken (image, read32 (ip), &handle_class);
3204                         ip += 4;
3205                         vt_alloc (&handle_class->byval_arg, sp);
3206                         stackval_from_data (&handle_class->byval_arg, sp, (char*)&handle);
3207                         ++sp;
3208                         BREAK;
3209                 }
3210                 CASE (CEE_CONV_OVF_I)
3211                         ++ip;
3212                         --sp;
3213                         /* FIXME: check overflow. */
3214                         switch (sp->type) {
3215                         case VAL_I32:
3216                                 sp->data.p = (gpointer)(mono_i) sp->data.i;
3217                                 break;
3218                         case VAL_I64:
3219                                 sp->data.p = (gpointer)(mono_i) sp->data.l;
3220                                 break;
3221                         case VAL_NATI:
3222                                 break;
3223                         case VAL_DOUBLE:
3224                                 sp->data.p = (gpointer)(mono_i) sp->data.f;
3225                                 break;
3226                         default:
3227                                 ves_abort ();
3228                         }
3229                         sp->type = VAL_NATI;
3230                         ++sp;
3231                         BREAK;
3232                 CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
3233                 CASE (CEE_ADD_OVF)
3234                         --sp;
3235                         /* FIXME: check overflow */
3236                         if (sp->type == VAL_I32) {
3237                                 if (CHECK_ADD_OVERFLOW (sp [-1].data.i, GET_NATI (sp [0])))
3238                                         THROW_EX (mono_get_exception_overflow (), ip);
3239                                 sp [-1].data.i = (guint32)sp [-1].data.i + (guint32)GET_NATI (sp [0]);
3240                         } else if (sp->type == VAL_I64) {
3241                                 if (CHECK_ADD_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
3242                                         THROW_EX (mono_get_exception_overflow (), ip);
3243                                 sp [-1].data.l = (guint64)sp [-1].data.l + (guint64)sp [0].data.l;
3244                         } else if (sp->type == VAL_DOUBLE)
3245                                 sp [-1].data.f += sp [0].data.f;
3246                         else {
3247                                 char *p = sp [-1].data.p;
3248                                 p += GET_NATI (sp [0]);
3249                                 sp [-1].data.p = p;
3250                         }
3251                         ++ip;
3252                         BREAK;
3253                 CASE (CEE_ADD_OVF_UN)
3254                         --sp;
3255                         /* FIXME: check overflow, make unsigned */
3256                         if (sp->type == VAL_I32) {
3257                                 if (CHECK_ADD_OVERFLOW_UN (sp [-1].data.i, GET_NATI (sp [0])))
3258                                         THROW_EX (mono_get_exception_overflow (), ip);
3259                                 sp [-1].data.i = (guint32)sp [-1].data.i + (guint32)GET_NATI (sp [0]);
3260                         } else if (sp->type == VAL_I64) {
3261                                 if (CHECK_ADD_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
3262                                         THROW_EX (mono_get_exception_overflow (), ip);
3263                                 sp [-1].data.l = (guint64)sp [-1].data.l + (guint64)sp [0].data.l;
3264                         } else if (sp->type == VAL_DOUBLE)
3265                                 sp [-1].data.f += sp [0].data.f;
3266                         else {
3267                                 char *p = sp [-1].data.p;
3268                                 p += GET_NATI (sp [0]);
3269                                 sp [-1].data.p = p;
3270                         }
3271                         ++ip;
3272                         BREAK;
3273                 CASE (CEE_MUL_OVF)
3274                         ++ip;
3275                         --sp;
3276                         /* FIXME: check overflow */
3277                         if (sp->type == VAL_I32)
3278                                 sp [-1].data.i *= (gint)GET_NATI (sp [0]);
3279                         else if (sp->type == VAL_I64)
3280                                 sp [-1].data.l *= sp [0].data.l;
3281                         else if (sp->type == VAL_DOUBLE)
3282                                 sp [-1].data.f *= sp [0].data.f;
3283                         BREAK;
3284                 CASE (CEE_MUL_OVF_UN)
3285                         ++ip;
3286                         --sp;
3287                         /* FIXME: check overflow, make unsigned */
3288                         if (sp->type == VAL_I32)
3289                                 sp [-1].data.i *= (gint)GET_NATI (sp [0]);
3290                         else if (sp->type == VAL_I64)
3291                                 sp [-1].data.l *= sp [0].data.l;
3292                         else if (sp->type == VAL_DOUBLE)
3293                                 sp [-1].data.f *= sp [0].data.f;
3294                         BREAK;
3295                 CASE (CEE_SUB_OVF)
3296                 CASE (CEE_SUB_OVF_UN)
3297                         ++ip;
3298                         --sp;
3299                         /* FIXME: handle undeflow/unsigned */
3300                         /* should probably consider the pointers as unsigned */
3301                         if (sp->type == VAL_I32)
3302                                 sp [-1].data.i -= GET_NATI (sp [0]);
3303                         else if (sp->type == VAL_I64)
3304                                 sp [-1].data.l -= sp [0].data.l;
3305                         else if (sp->type == VAL_DOUBLE)
3306                                 sp [-1].data.f -= sp [0].data.f;
3307                         else {
3308                                 char *p = sp [-1].data.p;
3309                                 p -= GET_NATI (sp [0]);
3310                                 sp [-1].data.p = p;
3311                         }
3312                         BREAK;
3313                 CASE (CEE_ENDFINALLY)
3314                         if (finally_ips) {
3315                                 ip = finally_ips->data;
3316                                 finally_ips = g_slist_remove (finally_ips, ip);
3317                                 goto main_loop;
3318                         }
3319                         if (frame->ex)
3320                                 goto handle_fault;
3321                         /*
3322                          * There was no exception, we continue normally at the target address.
3323                          */
3324                         ip = endfinally_ip;
3325                         BREAK;
3326                 CASE (CEE_LEAVE) /* Fall through */
3327                 CASE (CEE_LEAVE_S)
3328                         sp = frame->stack; /* empty the stack */
3329                         frame->ip = ip;
3330                         if (*ip == CEE_LEAVE_S) {
3331                                 ++ip;
3332                                 ip += (signed char) *ip;
3333                                 ++ip;
3334                         } else {
3335                                 ++ip;
3336                                 ip += (gint32) read32 (ip);
3337                                 ip += 4;
3338                         }
3339 #if 0
3340                         /*
3341                          * We may be either inside a try block or inside an handler.
3342                          * In the first case there was no exception and we go on
3343                          * executing the finally handlers and after that resume control
3344                          * at endfinally_ip.
3345                          * In the second case we need to clear the exception and
3346                          * continue directly at the target ip.
3347                          */
3348                         if (!frame->ex) {
3349                                 endfinally_ip = ip;
3350                                 goto handle_finally;
3351                         } else {
3352                                 frame->ex = NULL;
3353                                 frame->ex_handler = NULL;
3354                         }
3355 #endif
3356                         frame->ex = NULL;
3357                         frame->ex_handler = NULL;
3358                         endfinally_ip = ip;
3359                         goto handle_finally;
3360                         BREAK;
3361                 CASE (CEE_UNUSED26) 
3362                 CASE (CEE_UNUSED27) 
3363                 CASE (CEE_UNUSED28) 
3364                 CASE (CEE_UNUSED29) 
3365                 CASE (CEE_UNUSED30) 
3366                 CASE (CEE_UNUSED31) 
3367                 CASE (CEE_UNUSED32) 
3368                 CASE (CEE_UNUSED33) 
3369                 CASE (CEE_UNUSED34) 
3370                 CASE (CEE_UNUSED35) 
3371                 CASE (CEE_UNUSED36) 
3372                 CASE (CEE_UNUSED37) 
3373                 CASE (CEE_UNUSED38) 
3374                 CASE (CEE_UNUSED39) 
3375                 CASE (CEE_UNUSED40) 
3376                 CASE (CEE_UNUSED41) 
3377                 CASE (CEE_UNUSED42) 
3378                 CASE (CEE_UNUSED43) 
3379                 CASE (CEE_UNUSED44) 
3380                 CASE (CEE_UNUSED45) 
3381                 CASE (CEE_UNUSED46) 
3382                 CASE (CEE_UNUSED47) 
3383                 CASE (CEE_UNUSED48)
3384                 CASE (CEE_PREFIX7)
3385                 CASE (CEE_PREFIX6)
3386                 CASE (CEE_PREFIX5)
3387                 CASE (CEE_PREFIX4)
3388                 CASE (CEE_PREFIX3)
3389                 CASE (CEE_PREFIX2)
3390                 CASE (CEE_PREFIXREF) ves_abort(); BREAK;
3391                 /*
3392                  * Note: Exceptions thrown when executing a prefixed opcode need
3393                  * to take into account the number of prefix bytes (usually the
3394                  * throw point is just (ip - n_prefix_bytes).
3395                  */
3396                 SUB_SWITCH
3397                         ++ip;
3398                         switch (*ip) {
3399                         case CEE_ARGLIST: ves_abort(); break;
3400                         case CEE_CEQ: {
3401                                 gint32 result;
3402                                 ++ip;
3403                                 sp -= 2;
3404
3405                                 if (sp->type == VAL_I32)
3406                                         result = sp [0].data.i == (gint)GET_NATI (sp [1]);
3407                                 else if (sp->type == VAL_I64)
3408                                         result = sp [0].data.l == sp [1].data.l;
3409                                 else if (sp->type == VAL_DOUBLE) {
3410                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
3411                                                 result = 0;
3412                                         else
3413                                                 result = sp [0].data.f == sp [1].data.f;
3414                                 } else
3415                                         result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
3416                                 sp->type = VAL_I32;
3417                                 sp->data.i = result;
3418
3419                                 sp++;
3420                                 break;
3421                         }
3422                         case CEE_CGT: {
3423                                 gint32 result;
3424                                 ++ip;
3425                                 sp -= 2;
3426
3427                                 if (sp->type == VAL_I32)
3428                                         result = sp [0].data.i > (gint)GET_NATI (sp [1]);
3429                                 else if (sp->type == VAL_I64)
3430                                         result = sp [0].data.l > sp [1].data.l;
3431                                 else if (sp->type == VAL_DOUBLE) {
3432                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
3433                                                 result = 0;
3434                                         else
3435                                                 result = sp [0].data.f > sp [1].data.f;
3436                                 } else
3437                                         result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
3438                                 sp->type = VAL_I32;
3439                                 sp->data.i = result;
3440
3441                                 sp++;
3442                                 break;
3443                         }
3444                         case CEE_CGT_UN: {
3445                                 gint32 result;
3446                                 ++ip;
3447                                 sp -= 2;
3448
3449                                 if (sp->type == VAL_I32)
3450                                         result = (guint32)sp [0].data.i > (mono_u)GET_NATI (sp [1]);
3451                                 else if (sp->type == VAL_I64)
3452                                         result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
3453                                 else if (sp->type == VAL_DOUBLE)
3454                                         result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
3455                                 else
3456                                         result = (mono_u)GET_NATI (sp [0]) > (mono_u)GET_NATI (sp [1]);
3457                                 sp->type = VAL_I32;
3458                                 sp->data.i = result;
3459
3460                                 sp++;
3461                                 break;
3462                         }
3463                         case CEE_CLT: {
3464                                 gint32 result;
3465                                 ++ip;
3466                                 sp -= 2;
3467
3468                                 if (sp->type == VAL_I32)
3469                                         result = sp [0].data.i < (gint)GET_NATI (sp [1]);
3470                                 else if (sp->type == VAL_I64)
3471                                         result = sp [0].data.l < sp [1].data.l;
3472                                 else if (sp->type == VAL_DOUBLE) {
3473                                         if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
3474                                                 result = 0;
3475                                         else
3476                                                 result = sp [0].data.f < sp [1].data.f;
3477                                 } else
3478                                         result = (gint)GET_NATI (sp [0]) < (gint)GET_NATI (sp [1]);
3479                                 sp->type = VAL_I32;
3480                                 sp->data.i = result;
3481
3482                                 sp++;
3483                                 break;
3484                         }
3485                         case CEE_CLT_UN: {
3486                                 gint32 result;
3487                                 ++ip;
3488                                 sp -= 2;
3489
3490                                 if (sp->type == VAL_I32)
3491                                         result = (guint32)sp [0].data.i < (mono_u)GET_NATI (sp [1]);
3492                                 else if (sp->type == VAL_I64)
3493                                         result = (guint64)sp [0].data.l < (guint64)sp [1].data.l;
3494                                 else if (sp->type == VAL_DOUBLE)
3495                                         result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
3496                                 else
3497                                         result = (mono_u)GET_NATI (sp [0]) < (mono_u)GET_NATI (sp [1]);
3498                                 sp->type = VAL_I32;
3499                                 sp->data.i = result;
3500
3501                                 sp++;
3502                                 break;
3503                         }
3504                         case CEE_LDFTN:
3505                         case CEE_LDVIRTFTN: {
3506                                 int virtual = *ip == CEE_LDVIRTFTN;
3507                                 MonoMethod *m;
3508                                 guint32 token;
3509                                 ++ip;
3510                                 token = read32 (ip);
3511                                 ip += 4;
3512                                 m = mono_get_method (image, token, NULL);
3513                                 if (!m)
3514                                         THROW_EX (mono_get_exception_missing_method (), ip - 5);
3515                                 if (virtual) {
3516                                         --sp;
3517                                         if (!sp->data.p)
3518                                                 THROW_EX (mono_get_exception_null_reference (), ip - 5);
3519                                         m = get_virtual_method (domain, m, sp);
3520                                 }
3521                                 sp->type = VAL_NATI;
3522                                 sp->data.p = mono_create_method_pointer (m);
3523                                 sp->data.vt.klass = NULL;
3524                                 ++sp;
3525                                 break;
3526                         }
3527                         case CEE_UNUSED56: ves_abort(); break;
3528                         case CEE_LDARG: {
3529                                 guint32 arg_pos;
3530                                 ++ip;
3531                                 arg_pos = read16 (ip);
3532                                 ip += 2;
3533                                 vt_alloc (ARG_TYPE (signature, arg_pos), sp);
3534                                 stackval_from_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos));
3535                                 ++sp;
3536                                 break;
3537                         }
3538                         case CEE_LDARGA: {
3539                                 MonoType *t;
3540                                 MonoClass *c;
3541                                 guint32 anum;
3542
3543                                 ++ip;
3544                                 anum = read16 (ip);
3545                                 ip += 2;
3546                                 t = ARG_TYPE (signature, anum);
3547                                 c = mono_class_from_mono_type (t);
3548                                 sp->data.vt.klass = c;
3549                                 sp->data.vt.vt = ARG_POS (anum);
3550
3551                                 if (c->valuetype)
3552                                         sp->type = VAL_VALUETA;
3553                                 else
3554                                         sp->type = VAL_TP;
3555
3556                                 ++sp;
3557                                 break;
3558                         }
3559                         case CEE_STARG: {
3560                                 guint32 arg_pos;
3561                                 ++ip;
3562                                 arg_pos = read16 (ip);
3563                                 ip += 2;
3564                                 --sp;
3565                                 stackval_to_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos));
3566                                 vt_free (sp);
3567                                 break;
3568                         }
3569                         case CEE_LDLOC: {
3570                                 guint32 loc_pos;
3571                                 ++ip;
3572                                 loc_pos = read16 (ip);
3573                                 ip += 2;
3574                                 vt_alloc (LOCAL_TYPE (header, loc_pos), sp);
3575                                 stackval_from_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos));
3576                                 ++sp;
3577                                 break;
3578                         }
3579                         case CEE_LDLOCA: {
3580                                 MonoType *t;
3581                                 MonoClass *c;
3582                                 guint32 loc_pos;
3583
3584                                 ++ip;
3585                                 loc_pos = read16 (ip);
3586                                 ip += 2;
3587                                 t = LOCAL_TYPE (header, loc_pos);
3588                                 c =  mono_class_from_mono_type (t);
3589                                 sp->data.vt.vt = LOCAL_POS (loc_pos);
3590                                 sp->data.vt.klass = c;
3591
3592                                 if (c->valuetype) 
3593                                         sp->type = VAL_VALUETA;
3594                                 else
3595                                         sp->type = VAL_TP;
3596
3597                                 ++sp;
3598                                 break;
3599                         }
3600                         case CEE_STLOC: {
3601                                 guint32 loc_pos;
3602                                 ++ip;
3603                                 loc_pos = read16 (ip);
3604                                 ip += 2;
3605                                 --sp;
3606                                 stackval_to_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos));
3607                                 vt_free (sp);
3608                                 break;
3609                         }
3610                         case CEE_LOCALLOC:
3611                                 if (sp != frame->stack)
3612                                         THROW_EX (mono_get_exception_execution_engine (NULL), ip - 1);
3613                                 ++ip;
3614                                 sp->data.p = alloca (sp->data.i);
3615                                 sp->type = VAL_TP;
3616                                 break;
3617                         case CEE_UNUSED57: ves_abort(); break;
3618                         case CEE_ENDFILTER: ves_abort(); break;
3619                         case CEE_UNALIGNED_:
3620                                 ++ip;
3621                                 unaligned_address = 1;
3622                                 break;
3623                         case CEE_VOLATILE_:
3624                                 ++ip;
3625                                 volatile_address = 1;
3626                                 break;
3627                         case CEE_TAIL_:
3628                                 ++ip;
3629                                 tail_recursion = 1;
3630                                 break;
3631                         case CEE_INITOBJ: {
3632                                 guint32 token;
3633                                 ++ip;
3634                                 token = read32 (ip);
3635                                 ip += 4;
3636                                 /*
3637                                  * we ignore the value of token (I think we can as unspecified
3638                                  * behavior described in Partition II, 3.5).
3639                                  */
3640                                 --sp;
3641                                 g_assert (sp->type == VAL_VALUETA || sp->type == VAL_TP);
3642                                 memset (sp->data.vt.vt, 0, mono_class_value_size (sp->data.vt.klass, NULL));
3643                                 break;
3644                         }
3645                         case CEE_UNUSED68: ves_abort(); break;
3646                         case CEE_CPBLK:
3647                                 sp -= 3;
3648                                 if (!sp [0].data.p || !sp [1].data.p)
3649                                         THROW_EX (mono_get_exception_null_reference(), ip - 1);
3650                                 ++ip;
3651                                 /* FIXME: value and size may be int64... */
3652                                 memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
3653                                 break;
3654                         case CEE_INITBLK:
3655                                 sp -= 3;
3656                                 if (!sp [0].data.p)
3657                                         THROW_EX (mono_get_exception_null_reference(), ip - 1);
3658                                 ++ip;
3659                                 /* FIXME: value and size may be int64... */
3660                                 memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
3661                                 break;
3662                         case CEE_UNUSED69: ves_abort(); break;
3663                         case CEE_RETHROW:
3664                                 /* 
3665                                  * need to clarify what this should actually do:
3666                                  * start the search from the last found handler in
3667                                  * this method or continue in the caller or what.
3668                                  * Also, do we need to run finally/fault handlers after a retrow?
3669                                  * Well, this implementation will follow the usual search
3670                                  * for an handler, considering the current ip as throw spot.
3671                                  * We need to NULL frame->ex_handler for the later code to
3672                                  * actually run the new found handler.
3673                                  */
3674                                 frame->ex_handler = NULL;
3675                                 THROW_EX (frame->ex, ip - 1);
3676                                 break;
3677                         case CEE_UNUSED: ves_abort(); break;
3678                         case CEE_SIZEOF: {
3679                                 guint32 token;
3680                                 MonoType *type;
3681                                 int align;
3682                                 ++ip;
3683                                 token = read32 (ip);
3684                                 ip += 4;
3685                                 type = mono_type_create_from_typespec (image, token);
3686                                 sp->type = VAL_I32;
3687                                 sp->data.i = mono_type_size (type, &align);
3688                                 mono_metadata_free_type (type);
3689                                 ++sp;
3690                                 break;
3691                         }
3692                         case CEE_REFANYTYPE: ves_abort(); break;
3693                         case CEE_UNUSED52: 
3694                         case CEE_UNUSED53: 
3695                         case CEE_UNUSED54: 
3696                         case CEE_UNUSED55: 
3697                         case CEE_UNUSED70: 
3698                         default:
3699                                 g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-header->code);
3700                         }
3701                         continue;
3702                 DEFAULT;
3703                 }
3704         }
3705
3706         g_assert_not_reached ();
3707         /*
3708          * Exception handling code.
3709          * The exception object is stored in frame->ex.
3710          */
3711
3712         handle_exception:
3713         {
3714                 int i;
3715                 guint32 ip_offset;
3716                 MonoInvocation *inv;
3717                 MonoMethodHeader *hd;
3718                 MonoExceptionClause *clause;
3719                 char *message;
3720                 MonoObject *ex_obj;
3721
3722                 if (die_on_exception)
3723                         goto die_on_ex;
3724                 
3725                 for (inv = frame; inv; inv = inv->parent) {
3726                         if (inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
3727                                 continue;
3728                         if (inv->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
3729                                 continue;
3730                         hd = ((MonoMethodNormal*)inv->method)->header;
3731                         ip_offset = inv->ip - hd->code;
3732                         for (i = 0; i < hd->num_clauses; ++i) {
3733                                 clause = &hd->clauses [i];
3734                                 if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3735                                         if (!clause->flags) {
3736                                                 if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (inv->method->klass->image, clause->token_or_filter))) {
3737                                                         /* 
3738                                                          * OK, we found an handler, now we need to execute the finally
3739                                                          * and fault blocks before branching to the handler code.
3740                                                          */
3741                                                         inv->ex_handler = clause;
3742                                                         /*
3743                                                          * It seems that if the catch handler is found in the same method,
3744                                                          * it gets executed before the finally handler.
3745                                                          */
3746                                                         if (inv == frame)
3747                                                                 goto handle_fault;
3748                                                         else
3749                                                                 goto handle_finally;
3750                                                 }
3751                                         } else {
3752                                                 /* FIXME: handle filter clauses */
3753                                                 g_assert (0);
3754                                         }
3755                                 }
3756                         }
3757                 }
3758                 /*
3759                  * If we get here, no handler was found: print a stack trace.
3760                  */
3761 die_on_ex:
3762                 ex_obj = (MonoObject*)frame->ex;
3763                 mono_unhandled_exception (ex_obj);
3764                 exit (1);
3765         }
3766         handle_finally:
3767         {
3768                 int i;
3769                 guint32 ip_offset;
3770                 MonoExceptionClause *clause;
3771                 
3772                 if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
3773                         DEBUG_LEAVE ();
3774                         return;
3775                 }
3776                 ip_offset = frame->ip - header->code;
3777
3778                 for (i = 0; i < header->num_clauses; ++i) {
3779                         clause = &header->clauses [i];
3780                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3781                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
3782                                         ip = header->code + clause->handler_offset;
3783                                         finally_ips = g_slist_append (finally_ips, ip);
3784                                 }
3785                         }
3786                 }
3787                 if (finally_ips) {
3788                         ip = finally_ips->data;
3789                         finally_ips = g_slist_remove (finally_ips, ip);
3790                         goto main_loop;
3791                 }
3792
3793                 /*
3794                  * If an exception is set, we need to execute the fault handler, too,
3795                  * otherwise, we continue normally.
3796                  */
3797                 if (frame->ex)
3798                         goto handle_fault;
3799                 ip = endfinally_ip;
3800                 goto main_loop;
3801         }
3802         handle_fault:
3803         {
3804                 int i;
3805                 guint32 ip_offset;
3806                 MonoExceptionClause *clause;
3807                 
3808                 ip_offset = frame->ip - header->code;
3809                 for (i = 0; i < header->num_clauses; ++i) {
3810                         clause = &header->clauses [i];
3811                         if (clause->flags == 3 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
3812                                 ip = header->code + clause->handler_offset;
3813                                 goto main_loop;
3814                         }
3815                 }
3816                 /*
3817                  * If the handler for the exception was found in this method, we jump
3818                  * to it right away, otherwise we return and let the caller run
3819                  * the finally, fault and catch blocks.
3820                  * This same code should be present in the endfault opcode, but it
3821                  * is corrently not assigned in the ECMA specs: LAMESPEC.
3822                  */
3823                 if (frame->ex_handler) {
3824                         ip = header->code + frame->ex_handler->handler_offset;
3825                         sp = frame->stack;
3826                         sp->type = VAL_OBJ;
3827                         sp->data.p = frame->ex;
3828                         ++sp;
3829                         goto main_loop;
3830                 }
3831                 DEBUG_LEAVE ();
3832                 return;
3833         }
3834         
3835 }
3836
3837 static int 
3838 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
3839 {
3840         MonoImage *image = assembly->image;
3841         MonoCLIImageInfo *iinfo;
3842         MonoMethod *method;
3843         MonoObject *exc = NULL;
3844         int rval;
3845
3846         iinfo = image->image_info;
3847         method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
3848         if (!method)
3849                 g_error ("No entry point method found in %s", image->name);
3850
3851         rval = mono_runtime_run_main (method, argc, argv, &exc);
3852
3853         return rval;
3854 }
3855
3856 static void
3857 usage (void)
3858 {
3859         fprintf (stderr,
3860                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001 Ximian, Inc.\n\n"
3861                  "Usage is: mint [options] executable args...\n", VERSION);
3862         fprintf (stderr,
3863                  "Valid Options are:\n"
3864 #ifdef DEBUG_INTERP
3865                  "--debug\n"
3866 #endif
3867                  "--help\n"
3868                  "--trace\n"
3869                  "--traceops\n"
3870                  "--traceclassinit\n"
3871                  "--noptr\t\t\tdon't print pointer addresses in trace output\n"
3872                  "--dieonex\n"
3873                  "--profile\n"
3874                  "--debug method_name\n"
3875                  "--print-vtable\n"
3876                  "--opcode-count\n");
3877         exit (1);
3878 }
3879
3880 #ifdef RUN_TEST
3881 static void
3882 test_load_class (MonoImage* image)
3883 {
3884         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
3885         MonoClass *klass;
3886         int i;
3887
3888         for (i = 1; i <= t->rows; ++i) {
3889                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
3890                 mono_class_init (klass);
3891         }
3892 }
3893 #endif
3894
3895 static MonoException * segv_exception = NULL;
3896
3897 static void
3898 segv_handler (int signum)
3899 {
3900         signal (signum, segv_handler);
3901         mono_raise_exception (segv_exception);
3902 }
3903
3904 int 
3905 main (int argc, char *argv [])
3906 {
3907         MonoDomain *domain;
3908         MonoAssembly *assembly;
3909         int retval = 0, i, ocount = 0;
3910         char *file, *error;
3911
3912         if (argc < 2)
3913                 usage ();
3914
3915         for (i = 1; i < argc && argv [i][0] == '-'; i++){
3916                 if (strcmp (argv [i], "--trace") == 0)
3917                         global_tracing = 1;
3918                 if (strcmp (argv [i], "--noptr") == 0)
3919                         global_no_pointers = 1;
3920                 if (strcmp (argv [i], "--traceops") == 0)
3921                         global_tracing = 2;
3922                 if (strcmp (argv [i], "--dieonex") == 0)
3923                         die_on_exception = 1;
3924                 if (strcmp (argv [i], "--print-vtable") == 0)
3925                         mono_print_vtable = TRUE;
3926                 if (strcmp (argv [i], "--profile") == 0)
3927                         mono_profiler_install_simple ();
3928                 if (strcmp (argv [i], "--opcode-count") == 0)
3929                         ocount = 1;
3930                 if (strcmp (argv [i], "--help") == 0)
3931                         usage ();
3932 #if DEBUG_INTERP
3933                 if (strcmp (argv [i], "--debug") == 0) {
3934                         MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
3935                         if (!desc)
3936                                 g_error ("Invalid method name '%s'", argv [i]);
3937                         db_methods = g_list_append (db_methods, desc);
3938                 }
3939 #endif
3940         }
3941         
3942         file = argv [i];
3943
3944         if (!file)
3945                 usage ();
3946
3947         g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
3948         g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
3949
3950         mono_init_icall ();
3951         mono_add_internal_call ("System.Array::Set", ves_array_set);
3952         mono_add_internal_call ("System.Array::Get", ves_array_get);
3953         mono_add_internal_call ("System.Array::Address", ves_array_element_address);
3954
3955         frame_thread_id = TlsAlloc ();
3956         TlsSetValue (frame_thread_id, NULL);
3957
3958         mono_install_runtime_invoke (interp_mono_runtime_invoke);
3959         mono_install_remoting_trampoline (interp_create_remoting_trampoline);
3960
3961         mono_install_handler (interp_ex_handler);
3962
3963         InitializeCriticalSection (&metadata_lock);
3964         domain = mono_init (file);
3965         mono_runtime_init (domain);
3966         mono_thread_init (domain, NULL);
3967         mono_network_init ();
3968
3969         assembly = mono_domain_assembly_open (domain, file);
3970
3971         if (!assembly){
3972                 fprintf (stderr, "Can not open image %s\n", file);
3973                 exit (1);
3974         }
3975
3976
3977 #ifdef RUN_TEST
3978         test_load_class (assembly->image);
3979 #else
3980         error = mono_verify_corlib ();
3981         if (error) {
3982                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
3983                 exit (1);
3984         }
3985         segv_exception = mono_get_exception_null_reference ();
3986         segv_exception->message = mono_string_new (domain, "Segmentation fault");
3987         signal (SIGSEGV, segv_handler);
3988
3989         retval = ves_exec (domain, assembly, argc - i, argv + i);
3990 #endif
3991         mono_profiler_shutdown ();
3992         
3993         mono_network_cleanup ();
3994         mono_thread_cleanup ();
3995
3996         mono_domain_unload (domain, TRUE);
3997
3998 #if DEBUG_INTERP
3999         if (ocount) {
4000                 fprintf (stderr, "opcode count: %ld\n", opcode_count);
4001                 fprintf (stderr, "fcall count: %ld\n", fcall_count);
4002         }
4003 #endif
4004         return retval;
4005 }
4006
4007
4008