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