619c3a659e6c05277b7f9fb14f3524034ac32bb7
[mono.git] / mono / mini / interp / interp.c
1 /**
2  * \file
3  * PLEASE NOTE: This is a research prototype.
4  *
5  *
6  * interp.c: Interpreter for CIL byte codes
7  *
8  * Authors:
9  *   Paolo Molaro (lupus@ximian.com)
10  *   Miguel de Icaza (miguel@ximian.com)
11  *   Dietmar Maurer (dietmar@ximian.com)
12  *
13  * (C) 2001, 2002 Ximian, Inc.
14  */
15 #ifndef __USE_ISOC99
16 #define __USE_ISOC99
17 #endif
18 #include "config.h"
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <glib.h>
23 #include <setjmp.h>
24 #include <signal.h>
25 #include <math.h>
26 #include <locale.h>
27
28 #include <mono/utils/gc_wrapper.h>
29
30 #ifdef HAVE_ALLOCA_H
31 #   include <alloca.h>
32 #else
33 #   ifdef __CYGWIN__
34 #      define alloca __builtin_alloca
35 #   endif
36 #endif
37
38 /* trim excessive headers */
39 #include <mono/metadata/image.h>
40 #include <mono/metadata/assembly-internals.h>
41 #include <mono/metadata/cil-coff.h>
42 #include <mono/metadata/mono-endian.h>
43 #include <mono/metadata/tabledefs.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/reflection-internals.h>
52 #include <mono/metadata/exception.h>
53 #include <mono/metadata/verify.h>
54 #include <mono/metadata/opcodes.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/mono-config.h>
57 #include <mono/metadata/marshal.h>
58 #include <mono/metadata/environment.h>
59 #include <mono/metadata/mono-debug.h>
60
61 #include "interp.h"
62 #include "interp-internals.h"
63 #include "mintops.h"
64 #include "hacks.h"
65
66 #include <mono/mini/mini.h>
67 #include <mono/mini/jit-icalls.h>
68
69
70 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
71 #ifdef _WIN32
72 #define isnan _isnan
73 #define finite _finite
74 #endif
75 #ifndef HAVE_FINITE
76 #ifdef HAVE_ISFINITE
77 #define finite isfinite
78 #endif
79 #endif
80
81 static inline void
82 init_frame (MonoInvocation *frame, MonoInvocation *parent_frame, RuntimeMethod *rmethod, stackval *method_args, stackval *method_retval)
83 {
84         frame->parent = parent_frame;
85         frame->stack_args = method_args;
86         frame->retval = method_retval;
87         frame->runtime_method = rmethod;
88         frame->ex = NULL;
89         frame->ip = NULL;
90         frame->invoke_trap = 0;
91 }
92
93 #define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) do { \
94         RuntimeMethod *_rmethod = mono_interp_get_runtime_method ((domain), (mono_method), (error));    \
95         init_frame ((frame), (parent_frame), _rmethod, (method_args), (method_retval)); \
96         } while (0)
97
98 /*
99  * List of classes whose methods will be executed by transitioning to JITted code.
100  * Used for testing.
101  */
102 GSList *jit_classes;
103
104 void ves_exec_method (MonoInvocation *frame);
105
106 static char* dump_stack (stackval *stack, stackval *sp);
107 static char* dump_frame (MonoInvocation *inv);
108 static MonoArray *get_trace_ips (MonoDomain *domain, MonoInvocation *top);
109 static void ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
110
111 typedef void (*ICallMethod) (MonoInvocation *frame);
112
113 static guint32 die_on_exception = 0;
114 static MonoNativeTlsKey thread_context_id;
115
116 static char* dump_args (MonoInvocation *inv);
117
118 #define DEBUG_INTERP 0
119 #define COUNT_OPS 0
120 #if DEBUG_INTERP
121 int mono_interp_traceopt = 2;
122 /* If true, then we output the opcodes as we interpret them */
123 static int global_tracing = 2;
124
125 static int debug_indent_level = 0;
126
127 static int break_on_method = 0;
128 static int nested_trace = 0;
129 static GList *db_methods = NULL;
130
131 static void
132 output_indent (void)
133 {
134         int h;
135
136         for (h = 0; h < debug_indent_level; h++)
137                 g_print ("  ");
138 }
139
140 static void
141 db_match_method (gpointer data, gpointer user_data)
142 {
143         MonoMethod *m = (MonoMethod*)user_data;
144         MonoMethodDesc *desc = data;
145
146         if (mono_method_desc_full_match (desc, m))
147                 break_on_method = 1;
148 }
149
150 static void debug_enter (MonoInvocation *frame, int *tracing)
151 {
152         if (db_methods) {
153                 g_list_foreach (db_methods, db_match_method, (gpointer)frame->runtime_method->method);
154                 if (break_on_method)
155                         *tracing = nested_trace ? (global_tracing = 2, 3) : 2;
156                 break_on_method = 0;
157         }
158         if (*tracing) {
159                 MonoMethod *method = frame->runtime_method->method;
160                 char *mn, *args = dump_args (frame);
161                 debug_indent_level++;
162                 output_indent ();
163                 mn = mono_method_full_name (method, FALSE);
164                 g_print ("(%p) Entering %s (", mono_thread_internal_current (), mn);
165                 g_free (mn);
166                 g_print  ("%s)\n", args);
167                 g_free (args);
168         }
169         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)
170                 mono_profiler_method_enter (frame->runtime_method->method);
171 }
172
173
174 #define DEBUG_LEAVE()   \
175         if (tracing) {  \
176                 char *mn, *args;        \
177                 args = dump_retval (frame);     \
178                 output_indent ();       \
179                 mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
180                 g_print  ("(%p) Leaving %s", mono_thread_internal_current (),  mn);     \
181                 g_free (mn); \
182                 g_print  (" => %s\n", args);    \
183                 g_free (args);  \
184                 debug_indent_level--;   \
185                 if (tracing == 3) global_tracing = 0; \
186         }       \
187         if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)    \
188                 mono_profiler_method_leave (frame->runtime_method->method);
189
190 #else
191
192 int mono_interp_traceopt = 0;
193 static void debug_enter (MonoInvocation *frame, int *tracing)
194 {
195 }
196 #define DEBUG_LEAVE()
197
198 #endif
199
200 static void
201 interp_ex_handler (MonoException *ex) {
202         MonoError error;
203         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
204         char *stack_trace;
205         if (context == NULL)
206                 return;
207         stack_trace = dump_frame (context->current_frame);
208         ex->stack_trace = mono_string_new (mono_domain_get(), stack_trace);
209         g_free (stack_trace);
210         if (context->current_env == NULL || strcmp(ex->object.vtable->klass->name, "ExecutionEngineException") == 0) {
211                 char *strace = mono_string_to_utf8_checked (ex->stack_trace, &error);
212                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
213                 fprintf(stderr, "Nothing can catch this exception: ");
214                 fprintf(stderr, "%s", ex->object.vtable->klass->name);
215                 if (ex->message != NULL) {
216                         char *m = mono_string_to_utf8_checked (ex->message, &error);
217                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
218                         fprintf(stderr, ": %s", m);
219                         g_free(m);
220                 }
221                 fprintf(stderr, "\n%s\n", strace);
222                 g_free (strace);
223                 if (ex->inner_ex != NULL) {
224                         ex = (MonoException *)ex->inner_ex;
225                         fprintf(stderr, "Inner exception: %s", ex->object.vtable->klass->name);
226                         if (ex->message != NULL) {
227                                 char *m = mono_string_to_utf8_checked (ex->message, &error);
228                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
229                                 fprintf(stderr, ": %s", m);
230                                 g_free(m);
231                         }
232                         strace = mono_string_to_utf8_checked (ex->stack_trace, &error);
233                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
234                         fprintf(stderr, "\n");
235                         fprintf(stderr, "%s\n", strace);
236                         g_free (strace);
237                 }
238                 /* wait for other threads to also collapse */
239                 // Sleep(1000); // TODO: proper sleep
240                 exit(1);
241         }
242         context->env_frame->ex = ex;
243         context->search_for_handler = 1;
244         longjmp (*context->current_env, 1);
245 }
246
247 static void
248 ves_real_abort (int line, MonoMethod *mh,
249                 const unsigned short *ip, stackval *stack, stackval *sp)
250 {
251         MonoError error;
252         fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
253         fprintf (stderr, "Line=%d IP=0x%04lx, Aborted execution\n", line,
254                  ip-(const unsigned short *)mono_method_get_header_checked (mh, &error)->code);
255                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
256         g_print ("0x%04x %02x\n",
257                  ip-(const unsigned short *)mono_method_get_header_checked (mh, &error)->code, *ip);
258         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
259         if (sp > stack)
260                 printf ("\t[%ld] 0x%08x %0.5f\n", sp-stack, sp[-1].data.i, sp[-1].data.f);
261 }
262
263 #define ves_abort() \
264         do {\
265                 ves_real_abort(__LINE__, frame->runtime_method->method, ip, frame->stack, sp); \
266                 THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
267         } while (0);
268
269 RuntimeMethod*
270 mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
271 {
272         RuntimeMethod *rtm;
273         MonoJitDomainInfo *info;
274         MonoMethodSignature *sig;
275         int i;
276
277         error_init (error);
278
279         info = domain_jit_info (domain);
280         mono_domain_jit_code_hash_lock (domain);
281         rtm = mono_internal_hash_table_lookup (&info->interp_code_hash, method);
282         mono_domain_jit_code_hash_unlock (domain);
283         if (rtm)
284                 return rtm;
285
286         sig = mono_method_signature (method);
287
288         rtm = mono_domain_alloc0 (domain, sizeof (RuntimeMethod));
289         rtm->method = method;
290         rtm->param_count = sig->param_count;
291         rtm->hasthis = sig->hasthis;
292         rtm->rtype = mini_get_underlying_type (sig->ret);
293         rtm->param_types = mono_domain_alloc0 (domain, sizeof (MonoType*) * sig->param_count);
294         for (i = 0; i < sig->param_count; ++i)
295                 rtm->param_types [i] = mini_get_underlying_type (sig->params [i]);
296
297         mono_domain_jit_code_hash_lock (domain);
298         if (!mono_internal_hash_table_lookup (&info->interp_code_hash, method))
299                 mono_internal_hash_table_insert (&info->interp_code_hash, method, rtm);
300         mono_domain_jit_code_hash_unlock (domain);
301
302         return rtm;
303 }
304
305 gpointer
306 mono_interp_create_trampoline (MonoDomain *domain, MonoMethod *method, MonoError *error)
307 {
308         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
309                 method = mono_marshal_get_synchronized_wrapper (method);
310         return mono_interp_get_runtime_method (domain, method, error);
311 }
312
313 static inline RuntimeMethod*
314 get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObject *obj)
315 {
316         MonoMethod *m = runtime_method->method;
317         MonoError error;
318
319         if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
320                 RuntimeMethod *ret = NULL;
321                 if (mono_object_is_transparent_proxy (obj)) {
322                         ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
323                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
324                 } else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
325                         ret = mono_interp_get_runtime_method (domain, mono_marshal_get_synchronized_wrapper (m), &error);
326                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
327                 } else {
328                         ret = runtime_method;
329                 }
330                 return ret;
331         }
332
333         mono_class_setup_vtable (obj->vtable->klass);
334
335         int slot = mono_method_get_vtable_slot (m);
336         if (mono_class_is_interface (m->klass)) {
337                 g_assert (obj->vtable->klass != m->klass);
338                 /* TODO: interface offset lookup is slow, go through IMT instead */
339                 gboolean non_exact_match;
340                 slot += mono_class_interface_offset_with_variance (obj->vtable->klass, m->klass, &non_exact_match);
341         }
342
343         MonoMethod *virtual_method = obj->vtable->klass->vtable [slot];
344         if (m->is_inflated && mono_method_get_context (m)->method_inst) {
345                 MonoGenericContext context = { NULL, NULL };
346
347                 if (mono_class_is_ginst (virtual_method->klass))
348                         context.class_inst = mono_class_get_generic_class (virtual_method->klass)->context.class_inst;
349                 else if (mono_class_is_gtd (virtual_method->klass))
350                         context.class_inst = mono_class_get_generic_container (virtual_method->klass)->context.class_inst;
351                 context.method_inst = mono_method_get_context (m)->method_inst;
352
353                 virtual_method = mono_class_inflate_generic_method_checked (virtual_method, &context, &error);
354                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
355         }
356
357         if (virtual_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
358                 virtual_method = mono_marshal_get_synchronized_wrapper (virtual_method);
359         }
360
361         RuntimeMethod *virtual_runtime_method = mono_interp_get_runtime_method (domain, virtual_method, &error);
362         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
363         return virtual_runtime_method;
364 }
365
366 static void inline
367 stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvoke)
368 {
369         if (type->byref) {
370                 switch (type->type) {
371                 case MONO_TYPE_OBJECT:
372                 case MONO_TYPE_CLASS:
373                 case MONO_TYPE_STRING:
374                 case MONO_TYPE_ARRAY:
375                 case MONO_TYPE_SZARRAY:
376                         break;
377                 default:
378                         break;
379                 }
380                 result->data.p = *(gpointer*)data;
381                 return;
382         }
383         switch (type->type) {
384         case MONO_TYPE_VOID:
385                 return;
386         case MONO_TYPE_I1:
387                 result->data.i = *(gint8*)data;
388                 return;
389         case MONO_TYPE_U1:
390         case MONO_TYPE_BOOLEAN:
391                 result->data.i = *(guint8*)data;
392                 return;
393         case MONO_TYPE_I2:
394                 result->data.i = *(gint16*)data;
395                 return;
396         case MONO_TYPE_U2:
397         case MONO_TYPE_CHAR:
398                 result->data.i = *(guint16*)data;
399                 return;
400         case MONO_TYPE_I4:
401                 result->data.i = *(gint32*)data;
402                 return;
403         case MONO_TYPE_U:
404         case MONO_TYPE_I:
405                 result->data.nati = *(mono_i*)data;
406                 return;
407         case MONO_TYPE_PTR:
408                 result->data.p = *(gpointer*)data;
409                 return;
410         case MONO_TYPE_U4:
411                 result->data.i = *(guint32*)data;
412                 return;
413         case MONO_TYPE_R4:
414                 result->data.f = *(float*)data;
415                 return;
416         case MONO_TYPE_I8:
417         case MONO_TYPE_U8:
418                 result->data.l = *(gint64*)data;
419                 return;
420         case MONO_TYPE_R8:
421                 result->data.f = *(double*)data;
422                 return;
423         case MONO_TYPE_STRING:
424         case MONO_TYPE_SZARRAY:
425         case MONO_TYPE_CLASS:
426         case MONO_TYPE_OBJECT:
427         case MONO_TYPE_ARRAY:
428                 result->data.p = *(gpointer*)data;
429                 return;
430         case MONO_TYPE_VALUETYPE:
431                 if (type->data.klass->enumtype) {
432                         stackval_from_data (mono_class_enum_basetype (type->data.klass), result, data, pinvoke);
433                         return;
434                 } else
435                         mono_value_copy (result->data.vt, data, type->data.klass);
436                 return;
437         case MONO_TYPE_GENERICINST:
438                 stackval_from_data (&type->data.generic_class->container_class->byval_arg, result, data, pinvoke);
439                 return;
440         default:
441                 g_warning ("got type 0x%02x", type->type);
442                 g_assert_not_reached ();
443         }
444 }
445
446 static void inline
447 stackval_to_data (MonoType *type, stackval *val, char *data, gboolean pinvoke)
448 {
449         if (type->byref) {
450                 gpointer *p = (gpointer*)data;
451                 *p = val->data.p;
452                 return;
453         }
454         /* printf ("TODAT0 %p\n", data); */
455         switch (type->type) {
456         case MONO_TYPE_I1:
457         case MONO_TYPE_U1: {
458                 guint8 *p = (guint8*)data;
459                 *p = val->data.i;
460                 return;
461         }
462         case MONO_TYPE_BOOLEAN: {
463                 guint8 *p = (guint8*)data;
464                 *p = (val->data.i != 0);
465                 return;
466         }
467         case MONO_TYPE_I2:
468         case MONO_TYPE_U2:
469         case MONO_TYPE_CHAR: {
470                 guint16 *p = (guint16*)data;
471                 *p = val->data.i;
472                 return;
473         }
474         case MONO_TYPE_I: {
475                 mono_i *p = (mono_i*)data;
476                 /* In theory the value used by stloc should match the local var type
477                    but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
478                    a native int - both by csc and mcs). Not sure what to do about sign extension
479                    as it is outside the spec... doing the obvious */
480                 *p = (mono_i)val->data.nati;
481                 return;
482         }
483         case MONO_TYPE_U: {
484                 mono_u *p = (mono_u*)data;
485                 /* see above. */
486                 *p = (mono_u)val->data.nati;
487                 return;
488         }
489         case MONO_TYPE_I4:
490         case MONO_TYPE_U4: {
491                 gint32 *p = (gint32*)data;
492                 *p = val->data.i;
493                 return;
494         }
495         case MONO_TYPE_I8:
496         case MONO_TYPE_U8: {
497                 gint64 *p = (gint64*)data;
498                 *p = val->data.l;
499                 return;
500         }
501         case MONO_TYPE_R4: {
502                 float *p = (float*)data;
503                 *p = val->data.f;
504                 return;
505         }
506         case MONO_TYPE_R8: {
507                 double *p = (double*)data;
508                 *p = val->data.f;
509                 return;
510         }
511         case MONO_TYPE_STRING:
512         case MONO_TYPE_SZARRAY:
513         case MONO_TYPE_CLASS:
514         case MONO_TYPE_OBJECT:
515         case MONO_TYPE_ARRAY: {
516                 gpointer *p = (gpointer *) data;
517                 mono_gc_wbarrier_generic_store (p, val->data.p);
518                 return;
519         }
520         case MONO_TYPE_PTR: {
521                 gpointer *p = (gpointer *) data;
522                 *p = val->data.p;
523                 return;
524         }
525         case MONO_TYPE_VALUETYPE:
526                 if (type->data.klass->enumtype) {
527                         stackval_to_data (mono_class_enum_basetype (type->data.klass), val, data, pinvoke);
528                         return;
529                 } else
530                         mono_value_copy (data, val->data.vt, type->data.klass);
531                 return;
532         case MONO_TYPE_GENERICINST:
533                 stackval_to_data (&type->data.generic_class->container_class->byval_arg, val, data, pinvoke);
534                 return;
535         default:
536                 g_warning ("got type %x", type->type);
537                 g_assert_not_reached ();
538         }
539 }
540
541 static void
542 fill_in_trace (MonoException *exception, MonoInvocation *frame)
543 {
544         char *stack_trace = dump_frame (frame);
545         MonoDomain *domain = mono_domain_get();
546         (exception)->stack_trace = mono_string_new (domain, stack_trace);
547         (exception)->trace_ips = get_trace_ips (domain, frame);
548         g_free (stack_trace);
549 }
550
551 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
552
553 #define THROW_EX(exception,ex_ip)       \
554         do {\
555                 frame->ip = (ex_ip);            \
556                 frame->ex = (MonoException*)(exception);        \
557                 FILL_IN_TRACE(frame->ex, frame); \
558                 goto handle_exception;  \
559         } while (0)
560
561 static MonoObject*
562 ves_array_create (MonoInvocation *frame, MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
563 {
564         uintptr_t *lengths;
565         intptr_t *lower_bounds;
566         MonoObject *obj;
567         MonoError error;
568         int i;
569
570         lengths = alloca (sizeof (uintptr_t) * klass->rank * 2);
571         for (i = 0; i < sig->param_count; ++i) {
572                 lengths [i] = values->data.i;
573                 values ++;
574         }
575         if (klass->rank == sig->param_count) {
576                 /* Only lengths provided. */
577                 lower_bounds = NULL;
578         } else {
579                 /* lower bounds are first. */
580                 lower_bounds = (intptr_t *) lengths;
581                 lengths += klass->rank;
582         }
583         obj = (MonoObject*) mono_array_new_full_checked (domain, klass, lengths, lower_bounds, &error);
584         if (!mono_error_ok (&error)) {
585                 frame->ex = mono_error_convert_to_exception (&error);
586                 FILL_IN_TRACE (frame->ex, frame);
587         }
588         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
589         return obj;
590 }
591
592 static gint32
593 ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame)
594 {
595         g_assert (!frame->ex);
596         MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
597
598         guint32 pos = 0;
599         if (ao->bounds) {
600                 for (gint32 i = 0; i < ac->rank; i++) {
601                         guint32 idx = sp [i].data.i;
602                         guint32 lower = ao->bounds [i].lower_bound;
603                         guint32 len = ao->bounds [i].length;
604                         if (idx < lower || (idx - lower) >= len) {
605                                 frame->ex = mono_get_exception_index_out_of_range ();
606                                 FILL_IN_TRACE (frame->ex, frame);
607                                 return -1;
608                         }
609                         pos = (pos * len) + idx - lower;
610                 }
611         } else {
612                 pos = sp [0].data.i;
613                 if (pos >= ao->max_length) {
614                         frame->ex = mono_get_exception_index_out_of_range ();
615                         FILL_IN_TRACE (frame->ex, frame);
616                         return -1;
617                 }
618         }
619         return pos;
620 }
621
622 static void
623 ves_array_set (MonoInvocation *frame)
624 {
625         stackval *sp = frame->stack_args + 1;
626
627         MonoObject *o = frame->stack_args->data.p;
628         MonoArray *ao = (MonoArray *) o;
629         MonoClass *ac = o->vtable->klass;
630
631         g_assert (ac->rank >= 1);
632
633         gint32 pos = ves_array_calculate_index (ao, sp, frame);
634         if (frame->ex)
635                 return;
636
637         if (sp [ac->rank].data.p && !mono_object_class (o)->element_class->valuetype) {
638                 MonoError error;
639                 MonoObject *isinst = mono_object_isinst_checked (sp [ac->rank].data.p, mono_object_class (o)->element_class, &error);
640                 mono_error_cleanup (&error);
641                 if (!isinst) {
642                         frame->ex = mono_get_exception_array_type_mismatch ();
643                         FILL_IN_TRACE (frame->ex, frame);
644                         return;
645                 }
646         }
647
648         gint32 esize = mono_array_element_size (ac);
649         gpointer ea = mono_array_addr_with_size (ao, esize, pos);
650
651         MonoType *mt = mono_method_signature (frame->runtime_method->method)->params [ac->rank];
652         stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
653 }
654
655 static void
656 ves_array_get (MonoInvocation *frame)
657 {
658         stackval *sp = frame->stack_args + 1;
659
660         MonoObject *o = frame->stack_args->data.p;
661         MonoArray *ao = (MonoArray *) o;
662         MonoClass *ac = o->vtable->klass;
663
664         g_assert (ac->rank >= 1);
665
666         gint32 pos = ves_array_calculate_index (ao, sp, frame);
667         if (frame->ex)
668                 return;
669
670         gint32 esize = mono_array_element_size (ac);
671         gpointer ea = mono_array_addr_with_size (ao, esize, pos);
672
673         MonoType *mt = mono_method_signature (frame->runtime_method->method)->ret;
674         stackval_from_data (mt, frame->retval, ea, FALSE);
675 }
676
677 static gpointer
678 ves_array_element_address (MonoInvocation *frame, MonoClass *required_type, MonoArray *ao, stackval *sp, gboolean needs_typecheck)
679 {
680         MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
681
682         g_assert (ac->rank >= 1);
683
684         gint32 pos = ves_array_calculate_index (ao, sp, frame);
685         if (frame->ex)
686                 return NULL;
687
688         if (needs_typecheck && !mono_class_is_assignable_from (mono_object_class ((MonoObject *) ao)->element_class, required_type->element_class)) {
689                 frame->ex = mono_get_exception_array_type_mismatch ();
690                 FILL_IN_TRACE (frame->ex, frame);
691                 return NULL;
692         }
693         gint32 esize = mono_array_element_size (ac);
694         return mono_array_addr_with_size (ao, esize, pos);
695 }
696
697 void
698 interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data)
699 {
700         MonoError error;
701         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
702
703         MonoInvocation *frame = context->current_frame;
704
705         while (frame) {
706                 MonoStackFrameInfo fi;
707                 memset (&fi, 0, sizeof (MonoStackFrameInfo));
708
709                 /* TODO: hack to make some asserts happy. */
710                 fi.ji = (MonoJitInfo *) frame->runtime_method;
711
712                 if (frame->runtime_method)
713                         fi.method = fi.actual_method = frame->runtime_method->method;
714
715                 if (!fi.method || (fi.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (fi.method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
716                         fi.il_offset = -1;
717                         fi.type = FRAME_TYPE_MANAGED_TO_NATIVE;
718                 } else {
719                         MonoMethodHeader *hd = mono_method_get_header_checked (fi.method, &error);
720                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
721                         fi.type = FRAME_TYPE_MANAGED;
722                         fi.il_offset = frame->ip - (const unsigned short *) hd->code;
723                         if (!fi.method->wrapper_type)
724                                 fi.managed = TRUE;
725                 }
726
727                 if (func (&fi, ctx, user_data))
728                         return;
729                 frame = frame->parent;
730         }
731 }
732
733 static MonoPIFunc mono_interp_enter_icall_trampoline = NULL;
734
735 struct _MethodArguments {
736         size_t ilen;
737         gpointer *iargs;
738         size_t flen;
739         double *fargs;
740         gpointer *retval;
741         size_t is_float_ret;
742 };
743
744 typedef struct _MethodArguments MethodArguments;
745
746 // TODO: this function is also arch dependent (register width).
747 static MethodArguments* build_args_from_sig (MonoMethodSignature *sig, MonoInvocation *frame)
748 {
749         // TODO: don't malloc this data structure.
750         MethodArguments *margs = g_malloc0 (sizeof (MethodArguments));
751
752         if (sig->hasthis)
753                 margs->ilen++;
754
755         for (int i = 0; i < sig->param_count; i++) {
756                 guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
757                 switch (ptype) {
758                 case MONO_TYPE_BOOLEAN:
759                 case MONO_TYPE_CHAR:
760                 case MONO_TYPE_I1:
761                 case MONO_TYPE_U1:
762                 case MONO_TYPE_I2:
763                 case MONO_TYPE_U2:
764                 case MONO_TYPE_I4:
765                 case MONO_TYPE_U4:
766                 case MONO_TYPE_I:
767                 case MONO_TYPE_U:
768                 case MONO_TYPE_PTR:
769                 case MONO_TYPE_SZARRAY:
770                 case MONO_TYPE_CLASS:
771                 case MONO_TYPE_OBJECT:
772                 case MONO_TYPE_STRING:
773                 case MONO_TYPE_I8:
774                 case MONO_TYPE_VALUETYPE:
775                 case MONO_TYPE_GENERICINST:
776                         margs->ilen++;
777                         break;
778                 case MONO_TYPE_R4:
779                 case MONO_TYPE_R8:
780                         margs->flen++;
781                         break;
782                 default:
783                         g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype);
784                 }
785         }
786
787         if (margs->ilen > 0)
788                 margs->iargs = g_malloc0 (sizeof (gpointer) * margs->ilen);
789
790         if (margs->flen > 0)
791                 margs->fargs = g_malloc0 (sizeof (double) * margs->flen);
792
793         if (margs->ilen > 12)
794                 g_error ("build_args_from_sig: TODO, allocate gregs: %d\n", margs->ilen);
795
796         if (margs->flen > 3)
797                 g_error ("build_args_from_sig: TODO, allocate fregs: %d\n", margs->flen);
798
799
800         size_t int_i = 0;
801         size_t int_f = 0;
802
803         if (sig->hasthis) {
804                 margs->iargs [0] = frame->stack_args->data.p;
805                 int_i++;
806         }
807
808         for (int i = 0; i < sig->param_count; i++) {
809                 guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
810                 switch (ptype) {
811                 case MONO_TYPE_BOOLEAN:
812                 case MONO_TYPE_CHAR:
813                 case MONO_TYPE_I1:
814                 case MONO_TYPE_U1:
815                 case MONO_TYPE_I2:
816                 case MONO_TYPE_U2:
817                 case MONO_TYPE_I4:
818                 case MONO_TYPE_U4:
819                 case MONO_TYPE_I:
820                 case MONO_TYPE_U:
821                 case MONO_TYPE_PTR:
822                 case MONO_TYPE_SZARRAY:
823                 case MONO_TYPE_CLASS:
824                 case MONO_TYPE_OBJECT:
825                 case MONO_TYPE_STRING:
826                 case MONO_TYPE_I8:
827                 case MONO_TYPE_VALUETYPE:
828                 case MONO_TYPE_GENERICINST:
829                         margs->iargs [int_i] = frame->stack_args [i].data.p;
830 #if DEBUG_INTERP
831                         g_print ("build_args_from_sig: margs->iargs [%d]: %p (frame @ %d)\n", int_i, margs->iargs [int_i], i);
832 #endif
833                         int_i++;
834                         break;
835                 case MONO_TYPE_R4:
836                 case MONO_TYPE_R8:
837                         if (ptype == MONO_TYPE_R4)
838                                 * (float *) &(margs->fargs [int_f]) = (float) frame->stack_args [i].data.f;
839                         else
840                                 margs->fargs [int_f] = frame->stack_args [i].data.f;
841 #if DEBUG_INTERP
842                         g_print ("build_args_from_sig: margs->fargs [%d]: %p (%f) (frame @ %d)\n", int_f, margs->fargs [int_f], margs->fargs [int_f], i);
843 #endif
844                         int_f++;
845                         break;
846                 default:
847                         g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype);
848                 }
849         }
850
851         switch (sig->ret->type) {
852                 case MONO_TYPE_BOOLEAN:
853                 case MONO_TYPE_CHAR:
854                 case MONO_TYPE_I1:
855                 case MONO_TYPE_U1:
856                 case MONO_TYPE_I2:
857                 case MONO_TYPE_U2:
858                 case MONO_TYPE_I4:
859                 case MONO_TYPE_U4:
860                 case MONO_TYPE_I:
861                 case MONO_TYPE_U:
862                 case MONO_TYPE_PTR:
863                 case MONO_TYPE_SZARRAY:
864                 case MONO_TYPE_CLASS:
865                 case MONO_TYPE_OBJECT:
866                 case MONO_TYPE_STRING:
867                 case MONO_TYPE_I8:
868                 case MONO_TYPE_VALUETYPE:
869                 case MONO_TYPE_GENERICINST:
870                         margs->retval = &(frame->retval->data.p);
871                         break;
872                 case MONO_TYPE_R4:
873                 case MONO_TYPE_R8:
874                         margs->retval = &(frame->retval->data.p);
875                         margs->is_float_ret = 1;
876                         break;
877                 case MONO_TYPE_VOID:
878                         margs->retval = NULL;
879                         break;
880                 default:
881                         g_error ("build_args_from_sig: ret type not implemented yet: 0x%x\n", sig->ret->type);
882         }
883
884         return margs;
885 }
886
887 static void 
888 ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV addr, gboolean string_ctor, ThreadContext *context)
889 {
890         jmp_buf env;
891         MonoInvocation *old_frame = context->current_frame;
892         MonoInvocation *old_env_frame = context->env_frame;
893         jmp_buf *old_env = context->current_env;
894
895         if (setjmp (env)) {
896                 context->current_frame = old_frame;
897                 context->env_frame = old_env_frame;
898                 context->current_env = old_env;
899                 context->managed_code = 1;
900                 return;
901         }
902
903         frame->ex = NULL;
904         context->env_frame = frame;
905         context->current_env = &env;
906
907         g_assert (!frame->runtime_method);
908         if (!mono_interp_enter_icall_trampoline) {
909                 MonoTrampInfo *info;
910                 mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
911                 // TODO:
912                 // mono_tramp_info_register (info, NULL);
913         }
914
915         MethodArguments *margs = build_args_from_sig (sig, frame);
916 #if DEBUG_INTERP
917         g_print ("ICALL: mono_interp_enter_icall_trampoline = %p, addr = %p\n", mono_interp_enter_icall_trampoline, addr);
918         g_print ("margs(out): ilen=%d, flen=%d\n", margs->ilen, margs->flen);
919 #endif
920
921         context->current_frame = frame;
922         context->managed_code = 0;
923
924         mono_interp_enter_icall_trampoline (addr, margs);
925
926         context->managed_code = 1;
927         /* domain can only be changed by native code */
928         context->domain = mono_domain_get ();
929
930         if (*mono_thread_interruption_request_flag ()) {
931                 MonoException *exc = mono_thread_interruption_checkpoint ();
932                 if (exc) {
933                         frame->ex = exc;
934                         context->search_for_handler = 1;
935                 }
936         }
937         
938         if (!frame->ex && !MONO_TYPE_ISSTRUCT (sig->ret))
939                 stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
940
941         context->current_frame = old_frame;
942         context->env_frame = old_env_frame;
943         context->current_env = old_env;
944
945         g_free (margs->iargs);
946         g_free (margs->fargs);
947         g_free (margs);
948 }
949
950 void
951 mono_interp_init_delegate (MonoDelegate *del)
952 {
953         if (del->method)
954                 return;
955         /* shouldn't need a write barrier because we don't write a MonoObject into the field */
956         del->method = ((RuntimeMethod *) del->method_ptr)->method;
957 }
958
959 /*
960  * From the spec:
961  * runtime specifies that the implementation of the method is automatically
962  * provided by the runtime and is primarily used for the methods of delegates.
963  */
964 static void
965 ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
966 {
967         MonoMethod *method = frame->runtime_method->method;
968         const char *name = method->name;
969         MonoObject *obj = (MonoObject*) frame->stack_args->data.p;
970         MonoObject *isinst_obj;
971         MonoError error;
972
973         mono_class_init (method->klass);
974
975         if (method->klass == mono_defaults.array_class) {
976                 if (!strcmp (method->name, "UnsafeMov")) {
977                         /* TODO: layout checks */
978                         MonoType *mt = mono_method_signature (method)->ret;
979                         stackval_from_data (mt, frame->retval, (char *) frame->stack_args, FALSE);
980                         return;
981                 }
982         }
983
984         isinst_obj = mono_object_isinst_checked (obj, mono_defaults.array_class, &error);
985         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
986         if (obj && isinst_obj) {
987                 if (*name == 'S' && (strcmp (name, "Set") == 0)) {
988                         ves_array_set (frame);
989                         return;
990                 }
991                 if (*name == 'G' && (strcmp (name, "Get") == 0)) {
992                         ves_array_get (frame);
993                         return;
994                 }
995         }
996         
997         g_error ("Don't know how to exec runtime method %s.%s::%s", 
998                         method->klass->name_space, method->klass->name,
999                         method->name);
1000 }
1001
1002 static char*
1003 dump_stack (stackval *stack, stackval *sp)
1004 {
1005         stackval *s = stack;
1006         GString *str = g_string_new ("");
1007         
1008         if (sp == stack)
1009                 return g_string_free (str, FALSE);
1010         
1011         while (s < sp) {
1012                 g_string_append_printf (str, "[%p (%lld)] ", s->data.l, s->data.l);
1013                 ++s;
1014         }
1015         return g_string_free (str, FALSE);
1016 }
1017
1018 static void
1019 dump_stackval (GString *str, stackval *s, MonoType *type)
1020 {
1021         switch (type->type) {
1022         case MONO_TYPE_I1:
1023         case MONO_TYPE_U1:
1024         case MONO_TYPE_I2:
1025         case MONO_TYPE_U2:
1026         case MONO_TYPE_I4:
1027         case MONO_TYPE_U4:
1028         case MONO_TYPE_CHAR:
1029         case MONO_TYPE_BOOLEAN:
1030                 g_string_append_printf (str, "[%d] ", s->data.i);
1031                 break;
1032         case MONO_TYPE_STRING:
1033         case MONO_TYPE_SZARRAY:
1034         case MONO_TYPE_CLASS:
1035         case MONO_TYPE_OBJECT:
1036         case MONO_TYPE_ARRAY:
1037         case MONO_TYPE_PTR:
1038         case MONO_TYPE_I:
1039         case MONO_TYPE_U:
1040                 g_string_append_printf (str, "[%p] ", s->data.p);
1041                 break;
1042         case MONO_TYPE_VALUETYPE:
1043                 if (type->data.klass->enumtype)
1044                         g_string_append_printf (str, "[%d] ", s->data.i);
1045                 else
1046                         g_string_append_printf (str, "[vt:%p] ", s->data.p);
1047                 break;
1048         case MONO_TYPE_R4:
1049         case MONO_TYPE_R8:
1050                 g_string_append_printf (str, "[%g] ", s->data.f);
1051                 break;
1052         case MONO_TYPE_I8:
1053         case MONO_TYPE_U8:
1054         default: {
1055                 GString *res = g_string_new ("");
1056                 mono_type_get_desc (res, type, TRUE);
1057                 g_string_append_printf (str, "[{%s} %lld/0x%0llx] ", res->str, s->data.l, s->data.l);
1058                 g_string_free (res, TRUE);
1059                 break;
1060         }
1061         }
1062 }
1063
1064 static char*
1065 dump_args (MonoInvocation *inv)
1066 {
1067         GString *str = g_string_new ("");
1068         int i;
1069         MonoMethodSignature *signature = mono_method_signature (inv->runtime_method->method);
1070         
1071         if (signature->param_count == 0 && !signature->hasthis)
1072                 return g_string_free (str, FALSE);
1073
1074         if (signature->hasthis) {
1075                 MonoMethod *method = inv->runtime_method->method;
1076                 dump_stackval (str, inv->stack_args, &method->klass->byval_arg);
1077         }
1078
1079         for (i = 0; i < signature->param_count; ++i)
1080                 dump_stackval (str, inv->stack_args + (!!signature->hasthis) + i, signature->params [i]);
1081
1082         return g_string_free (str, FALSE);
1083 }
1084
1085 static char*
1086 dump_retval (MonoInvocation *inv)
1087 {
1088         GString *str = g_string_new ("");
1089         MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
1090
1091         if (ret->type != MONO_TYPE_VOID)
1092                 dump_stackval (str, inv->retval, ret);
1093
1094         return g_string_free (str, FALSE);
1095 }
1096  
1097 static char*
1098 dump_frame (MonoInvocation *inv)
1099 {
1100         GString *str = g_string_new ("");
1101         int i;
1102         char *args;
1103         MonoError error;
1104
1105         for (i = 0; inv; inv = inv->parent) {
1106                 if (inv->runtime_method != NULL) {
1107                         MonoMethod *method = inv->runtime_method->method;
1108                         MonoClass *k;
1109
1110                         int codep = 0;
1111                         const char * opname = "";
1112                         char *name;
1113                         gchar *source = NULL;
1114
1115                         k = method->klass;
1116
1117                         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
1118                                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
1119                                 MonoMethodHeader *hd = mono_method_get_header_checked (method, &error);
1120                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1121
1122                                 if (hd != NULL) {
1123                                         if (inv->ip) {
1124                                                 opname = mono_interp_opname [*inv->ip];
1125                                                 codep = inv->ip - inv->runtime_method->code;
1126                                                 source = g_strdup_printf ("%s:%d // (TODO: proper stacktrace)", method->name, codep);
1127                                         } else 
1128                                                 opname = "";
1129
1130 #if 0
1131                                         MonoDebugSourceLocation *minfo = mono_debug_lookup_method (method);
1132                                         source = mono_debug_method_lookup_location (minfo, codep);
1133 #endif
1134                                 }
1135                         }
1136                         args = dump_args (inv);
1137                         name = mono_method_full_name (method, TRUE);
1138                         if (source)
1139                                 g_string_append_printf (str, "#%d: 0x%05x %-10s in %s (%s) at %s\n", i, codep, opname, name, args, source);
1140                         else
1141                                 g_string_append_printf (str, "#%d: 0x%05x %-10s in %s (%s)\n", i, codep, opname, name, args);
1142                         g_free (name);
1143                         g_free (args);
1144                         g_free (source);
1145                         ++i;
1146                 }
1147         }
1148         return g_string_free (str, FALSE);
1149 }
1150
1151 static MonoArray *
1152 get_trace_ips (MonoDomain *domain, MonoInvocation *top)
1153 {
1154         int i;
1155         MonoArray *res;
1156         MonoInvocation *inv;
1157         MonoError error;
1158
1159         for (i = 0, inv = top; inv; inv = inv->parent)
1160                 if (inv->runtime_method != NULL)
1161                         ++i;
1162
1163         res = mono_array_new_checked (domain, mono_defaults.int_class, 2 * i, &error);
1164         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1165
1166         for (i = 0, inv = top; inv; inv = inv->parent)
1167                 if (inv->runtime_method != NULL) {
1168                         mono_array_set (res, gpointer, i, inv->runtime_method);
1169                         ++i;
1170                         mono_array_set (res, gpointer, i, (gpointer)inv->ip);
1171                         ++i;
1172                 }
1173
1174         return res;
1175 }
1176
1177
1178 #define MYGUINT64_MAX 18446744073709551615ULL
1179 #define MYGINT64_MAX 9223372036854775807LL
1180 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
1181
1182 #define MYGUINT32_MAX 4294967295U
1183 #define MYGINT32_MAX 2147483647
1184 #define MYGINT32_MIN (-MYGINT32_MAX -1)
1185         
1186 #define CHECK_ADD_OVERFLOW(a,b) \
1187         (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0  \
1188         : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
1189
1190 #define CHECK_SUB_OVERFLOW(a,b) \
1191         (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0   \
1192         : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
1193
1194 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1195         (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1196
1197 #define CHECK_SUB_OVERFLOW_UN(a,b) \
1198         (guint32)(a) < (guint32)(b) ? -1 : 0
1199
1200 #define CHECK_ADD_OVERFLOW64(a,b) \
1201         (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0  \
1202         : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
1203
1204 #define CHECK_SUB_OVERFLOW64(a,b) \
1205         (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0   \
1206         : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
1207
1208 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
1209         (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
1210
1211 #define CHECK_SUB_OVERFLOW64_UN(a,b) \
1212         (guint64)(a) < (guint64)(b) ? -1 : 0
1213
1214 #if SIZEOF_VOID_P == 4
1215 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
1216 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
1217 #else
1218 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
1219 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
1220 #endif
1221
1222 /* Resolves to TRUE if the operands would overflow */
1223 #define CHECK_MUL_OVERFLOW(a,b) \
1224         ((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
1225         (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
1226         (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
1227         (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
1228         (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
1229         (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
1230         (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
1231
1232 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1233         ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1234         (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1235
1236 #define CHECK_MUL_OVERFLOW64(a,b) \
1237         ((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
1238         (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
1239         (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
1240         (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
1241         (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
1242         (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
1243         (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
1244
1245 #define CHECK_MUL_OVERFLOW64_UN(a,b) \
1246         ((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
1247         (guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
1248
1249 #if SIZEOF_VOID_P == 4
1250 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
1251 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
1252 #else
1253 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
1254 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
1255 #endif
1256
1257 MonoObject*
1258 mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
1259 {
1260         MonoInvocation frame;
1261         ThreadContext * volatile context = mono_native_tls_get_value (thread_context_id);
1262         MonoObject *retval = NULL;
1263         MonoMethodSignature *sig = mono_method_signature (method);
1264         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1265         int i, type, isobject = 0;
1266         void *ret = NULL;
1267         stackval result;
1268         stackval *args = alloca (sizeof (stackval) * (sig->param_count + !!sig->hasthis));
1269         ThreadContext context_struct;
1270         MonoInvocation *old_frame = NULL;
1271         jmp_buf env;
1272
1273         error_init (error);
1274         if (exc)
1275                 *exc = NULL;
1276
1277         frame.ex = NULL;
1278
1279         if (setjmp(env)) {
1280                 if (context != &context_struct) {
1281                         context->domain = mono_domain_get ();
1282                         context->current_frame = old_frame;
1283                         context->managed_code = 0;
1284                 } else 
1285                         mono_native_tls_set_value (thread_context_id, NULL);
1286                 if (exc != NULL)
1287                         *exc = (MonoObject *)frame.ex;
1288                 return retval;
1289         }
1290
1291         if (context == NULL) {
1292                 context = &context_struct;
1293                 context_struct.base_frame = &frame;
1294                 context_struct.current_frame = NULL;
1295                 context_struct.env_frame = &frame;
1296                 context_struct.current_env = &env;
1297                 context_struct.search_for_handler = 0;
1298                 context_struct.managed_code = 0;
1299                 mono_native_tls_set_value (thread_context_id, context);
1300         }
1301         else
1302                 old_frame = context->current_frame;
1303
1304         context->domain = mono_domain_get ();
1305
1306         switch (sig->ret->type) {
1307         case MONO_TYPE_VOID:
1308                 break;
1309         case MONO_TYPE_STRING:
1310         case MONO_TYPE_OBJECT:
1311         case MONO_TYPE_CLASS:
1312         case MONO_TYPE_ARRAY:
1313         case MONO_TYPE_SZARRAY:
1314                 isobject = 1;
1315                 break;
1316         case MONO_TYPE_VALUETYPE:
1317                 retval = mono_object_new_checked (context->domain, klass, error);
1318                 ret = mono_object_unbox (retval);
1319                 if (!sig->ret->data.klass->enumtype)
1320                         result.data.vt = ret;
1321                 else
1322                         result.data.vt = alloca (mono_class_instance_size (klass));
1323                 break;
1324         case MONO_TYPE_GENERICINST:
1325                 if (!MONO_TYPE_IS_REFERENCE (sig->ret)) {
1326                         retval = mono_object_new_checked (context->domain, klass, error);
1327                         ret = mono_object_unbox (retval);
1328                         if (!sig->ret->data.klass->enumtype)
1329                                 result.data.vt = ret;
1330                         else
1331                                 result.data.vt = alloca (mono_class_instance_size (klass));
1332                 } else {
1333                         isobject = 1;
1334                 }
1335                 break;
1336
1337         case MONO_TYPE_PTR:
1338                 retval = mono_object_new_checked (context->domain, mono_defaults.int_class, error);
1339                 ret = mono_object_unbox (retval);
1340                 break;
1341         default:
1342                 retval = mono_object_new_checked (context->domain, klass, error);
1343                 ret = mono_object_unbox (retval);
1344                 break;
1345         }
1346
1347         if (sig->hasthis)
1348                 args [0].data.p = obj;
1349
1350         for (i = 0; i < sig->param_count; ++i) {
1351                 int a_index = i + !!sig->hasthis;
1352                 if (sig->params [i]->byref) {
1353                         args [a_index].data.p = params [i];
1354                         continue;
1355                 }
1356                 type = sig->params [i]->type;
1357 handle_enum:
1358                 switch (type) {
1359                 case MONO_TYPE_U1:
1360                 case MONO_TYPE_I1:
1361                 case MONO_TYPE_BOOLEAN:
1362                         args [a_index].data.i = *(MonoBoolean*)params [i];
1363                         break;
1364                 case MONO_TYPE_U2:
1365                 case MONO_TYPE_I2:
1366                 case MONO_TYPE_CHAR:
1367                         args [a_index].data.i = *(gint16*)params [i];
1368                         break;
1369 #if SIZEOF_VOID_P == 4
1370                 case MONO_TYPE_U: /* use VAL_POINTER? */
1371                 case MONO_TYPE_I:
1372 #endif
1373                 case MONO_TYPE_U4:
1374                 case MONO_TYPE_I4:
1375                         args [a_index].data.i = *(gint32*)params [i];
1376                         break;
1377 #if SIZEOF_VOID_P == 8
1378                 case MONO_TYPE_U:
1379                 case MONO_TYPE_I:
1380 #endif
1381                 case MONO_TYPE_U8:
1382                 case MONO_TYPE_I8:
1383                         args [a_index].data.l = *(gint64*)params [i];
1384                         break;
1385                 case MONO_TYPE_R4:
1386                         args [a_index].data.f = *(gfloat *) params [i];
1387                         break;
1388                 case MONO_TYPE_R8:
1389                         args [a_index].data.f = *(gdouble *) params [i];
1390                         break;
1391                 case MONO_TYPE_VALUETYPE:
1392                         if (sig->params [i]->data.klass->enumtype) {
1393                                 type = mono_class_enum_basetype (sig->params [i]->data.klass)->type;
1394                                 goto handle_enum;
1395                         } else {
1396                                 args [a_index].data.p = params [i];
1397                         }
1398                         break;
1399                 case MONO_TYPE_STRING:
1400                 case MONO_TYPE_PTR:
1401                 case MONO_TYPE_CLASS:
1402                 case MONO_TYPE_ARRAY:
1403                 case MONO_TYPE_SZARRAY:
1404                 case MONO_TYPE_OBJECT:
1405                 case MONO_TYPE_GENERICINST:
1406                         args [a_index].data.p = params [i];
1407                         break;
1408                 default:
1409                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1410                 }
1411         }
1412
1413         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
1414                 method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
1415         INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
1416         if (exc)
1417                 frame.invoke_trap = 1;
1418         context->managed_code = 1;
1419         ves_exec_method_with_context (&frame, context);
1420         context->managed_code = 0;
1421         if (context == &context_struct)
1422                 mono_native_tls_set_value (thread_context_id, NULL);
1423         else
1424                 context->current_frame = old_frame;
1425         if (frame.ex != NULL) {
1426                 if (exc != NULL) {
1427                         *exc = (MonoObject*) frame.ex;
1428                         return NULL;
1429                 }
1430                 if (context->current_env != NULL) {
1431                         context->env_frame->ex = frame.ex;
1432                         longjmp(*context->current_env, 1);
1433                 }
1434                 else
1435                         printf("dropped exception...\n");
1436         }
1437         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1438                 return NULL;
1439         if (isobject || method->string_ctor)
1440                 return result.data.p;
1441         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1442         return retval;
1443 }
1444
1445 typedef struct {
1446         RuntimeMethod *rmethod;
1447         gpointer this_arg;
1448         gpointer res;
1449         gpointer args [16];
1450         gpointer *many_args;
1451 } InterpEntryData;
1452
1453 /* Main function for entering the interpreter from compiled code */
1454 static void
1455 interp_entry (InterpEntryData *data)
1456 {
1457         MonoInvocation frame;
1458         RuntimeMethod *rmethod = data->rmethod;
1459         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
1460         ThreadContext context_struct;
1461         MonoInvocation *old_frame;
1462         stackval result;
1463         stackval *args;
1464         MonoMethod *method;
1465         MonoMethodSignature *sig;
1466         MonoType *type;
1467         int i;
1468
1469         method = rmethod->method;
1470         sig = mono_method_signature (method);
1471
1472         // FIXME: Optimize this
1473
1474         //printf ("%s\n", mono_method_full_name (method, 1));
1475
1476         frame.ex = NULL;
1477         if (context == NULL) {
1478                 context = &context_struct;
1479                 memset (context, 0, sizeof (ThreadContext));
1480                 context_struct.base_frame = &frame;
1481                 context_struct.env_frame = &frame;
1482                 mono_native_tls_set_value (thread_context_id, context);
1483         }
1484         else
1485                 old_frame = context->current_frame;
1486         context->domain = mono_domain_get ();
1487
1488         args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
1489         if (sig->hasthis)
1490                 args [0].data.p = data->this_arg;
1491
1492         gpointer *params;
1493         if (data->many_args)
1494                 params = data->many_args;
1495         else
1496                 params = data->args;
1497         for (i = 0; i < sig->param_count; ++i) {
1498                 int a_index = i + (sig->hasthis ? 1 : 0);
1499                 if (sig->params [i]->byref) {
1500                         args [a_index].data.p = params [i];
1501                         continue;
1502                 }
1503                 type = rmethod->param_types [i];
1504                 switch (type->type) {
1505                 case MONO_TYPE_U1:
1506                 case MONO_TYPE_I1:
1507                         args [a_index].data.i = *(MonoBoolean*)params [i];
1508                         break;
1509                 case MONO_TYPE_U2:
1510                 case MONO_TYPE_I2:
1511                         args [a_index].data.i = *(gint16*)params [i];
1512                         break;
1513                 case MONO_TYPE_U:
1514 #if SIZEOF_VOID_P == 4
1515                         args [a_index].data.p = GINT_TO_POINTER (*(guint32*)params [i]);
1516 #else
1517                         args [a_index].data.p = GINT_TO_POINTER (*(guint64*)params [i]);
1518 #endif
1519                         break;
1520                 case MONO_TYPE_I:
1521 #if SIZEOF_VOID_P == 4
1522                         args [a_index].data.p = GINT_TO_POINTER (*(gint32*)params [i]);
1523 #else
1524                         args [a_index].data.p = GINT_TO_POINTER (*(gint64*)params [i]);
1525 #endif
1526                         break;
1527                 case MONO_TYPE_U4:
1528                         args [a_index].data.i = *(guint32*)params [i];
1529                         break;
1530                 case MONO_TYPE_I4:
1531                         args [a_index].data.i = *(gint32*)params [i];
1532                         break;
1533                 case MONO_TYPE_U8:
1534                         args [a_index].data.l = *(guint64*)params [i];
1535                         break;
1536                 case MONO_TYPE_I8:
1537                         args [a_index].data.l = *(gint64*)params [i];
1538                         break;
1539                 case MONO_TYPE_PTR:
1540                 case MONO_TYPE_OBJECT:
1541                         args [a_index].data.p = *(MonoObject**)params [i];
1542                         break;
1543                 case MONO_TYPE_VALUETYPE:
1544                         args [a_index].data.p = params [i];
1545                         break;
1546                 case MONO_TYPE_GENERICINST:
1547                         if (MONO_TYPE_IS_REFERENCE (type))
1548                                 args [a_index].data.p = params [i];
1549                         else
1550                                 args [a_index].data.vt = params [i];
1551                         break;
1552                 default:
1553                         printf ("%s\n", mono_type_full_name (sig->params [i]));
1554                         NOT_IMPLEMENTED;
1555                         break;
1556                 }
1557         }
1558
1559         init_frame (&frame, context->current_frame, data->rmethod, args, &result);
1560         context->managed_code = 1;
1561
1562         type = rmethod->rtype;
1563         switch (type->type) {
1564         case MONO_TYPE_GENERICINST:
1565                 if (!MONO_TYPE_IS_REFERENCE (type))
1566                         frame.retval->data.vt = data->res;
1567                 break;
1568         case MONO_TYPE_VALUETYPE:
1569                 frame.retval->data.vt = data->res;
1570                 break;
1571         default:
1572                 break;
1573         }
1574
1575         ves_exec_method_with_context (&frame, context);
1576         context->managed_code = 0;
1577         if (context == &context_struct)
1578                 mono_native_tls_set_value (thread_context_id, NULL);
1579         else
1580                 context->current_frame = old_frame;
1581
1582         // FIXME:
1583         g_assert (frame.ex == NULL);
1584
1585         type = rmethod->rtype;
1586         switch (type->type) {
1587         case MONO_TYPE_VOID:
1588                 break;
1589         case MONO_TYPE_I1:
1590                 *(gint8*)data->res = frame.retval->data.i;
1591                 break;
1592         case MONO_TYPE_U1:
1593                 *(guint8*)data->res = frame.retval->data.i;
1594                 break;
1595         case MONO_TYPE_I2:
1596                 *(gint16*)data->res = frame.retval->data.i;
1597                 break;
1598         case MONO_TYPE_U2:
1599                 *(guint16*)data->res = frame.retval->data.i;
1600                 break;
1601         case MONO_TYPE_I4:
1602                 *(gint32*)data->res = frame.retval->data.i;
1603                 break;
1604         case MONO_TYPE_U4:
1605                 *(guint64*)data->res = frame.retval->data.i;
1606                 break;
1607         case MONO_TYPE_I8:
1608                 *(gint64*)data->res = frame.retval->data.i;
1609                 break;
1610         case MONO_TYPE_U8:
1611                 *(guint64*)data->res = frame.retval->data.i;
1612                 break;
1613         case MONO_TYPE_I:
1614 #if SIZEOF_VOID_P == 8
1615                 *(gint64*)data->res = (gint64)frame.retval->data.p;
1616 #else
1617                 *(gint32*)data->res = (gint32)frame.retval->data.p;
1618 #endif
1619                 break;
1620         case MONO_TYPE_U:
1621 #if SIZEOF_VOID_P == 8
1622                 *(guint64*)data->res = (guint64)frame.retval->data.p;
1623 #else
1624                 *(guint32*)data->res = (guint32)frame.retval->data.p;
1625 #endif
1626                 break;
1627         case MONO_TYPE_OBJECT:
1628                 /* No need for a write barrier */
1629                 *(MonoObject**)data->res = (MonoObject*)frame.retval->data.p;
1630                 break;
1631         case MONO_TYPE_GENERICINST:
1632                 if (MONO_TYPE_IS_REFERENCE (type)) {
1633                         *(MonoObject**)data->res = *(MonoObject**)frame.retval->data.p;
1634                 } else {
1635                         /* Already set before the call */
1636                 }
1637                 break;
1638         case MONO_TYPE_VALUETYPE:
1639                 /* Already set before the call */
1640                 break;
1641         default:
1642                 printf ("%s\n", mono_type_full_name (sig->ret));
1643                 NOT_IMPLEMENTED;
1644                 break;
1645         }
1646 }
1647
1648 static stackval * 
1649 do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
1650 {
1651         MonoInvocation *old_frame = context->current_frame;
1652         MonoInvocation *old_env_frame = context->env_frame;
1653         jmp_buf *old_env = context->current_env;
1654         jmp_buf env;
1655
1656         if (setjmp (env)) {
1657                 context->current_frame = old_frame;
1658                 context->env_frame = old_env_frame;
1659                 context->current_env = old_env;
1660                 context->managed_code = 1;
1661                 return sp;
1662         }
1663
1664         context->env_frame = context->current_frame;
1665         context->current_env = &env;
1666         context->managed_code = 0;
1667
1668         switch (op) {
1669         case MINT_ICALL_V_V: {
1670                 void (*func)() = ptr;
1671                 func ();
1672                 break;
1673         }
1674         case MINT_ICALL_V_P: {
1675                 gpointer (*func)() = ptr;
1676                 sp++;
1677                 sp [-1].data.p = func ();
1678                 break;
1679         }
1680         case MINT_ICALL_P_V: {
1681                 void (*func)(gpointer) = ptr;
1682                 func (sp [-1].data.p);
1683                 sp --;
1684                 break;
1685         }
1686         case MINT_ICALL_P_P: {
1687                 gpointer (*func)(gpointer) = ptr;
1688                 sp [-1].data.p = func (sp [-1].data.p);
1689                 break;
1690         }
1691         case MINT_ICALL_PP_V: {
1692                 void (*func)(gpointer,gpointer) = ptr;
1693                 sp -= 2;
1694                 func (sp [0].data.p, sp [1].data.p);
1695                 break;
1696         }
1697         case MINT_ICALL_PI_V: {
1698                 void (*func)(gpointer,int) = ptr;
1699                 sp -= 2;
1700                 func (sp [0].data.p, sp [1].data.i);
1701                 break;
1702         }
1703         case MINT_ICALL_PP_P: {
1704                 gpointer (*func)(gpointer,gpointer) = ptr;
1705                 --sp;
1706                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
1707                 break;
1708         }
1709         case MINT_ICALL_PI_P: {
1710                 gpointer (*func)(gpointer,int) = ptr;
1711                 --sp;
1712                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.i);
1713                 break;
1714         }
1715         case MINT_ICALL_PPP_V: {
1716                 void (*func)(gpointer,gpointer,gpointer) = ptr;
1717                 sp -= 3;
1718                 func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
1719                 break;
1720         }
1721         case MINT_ICALL_PPI_V: {
1722                 void (*func)(gpointer,gpointer,int) = ptr;
1723                 sp -= 3;
1724                 func (sp [0].data.p, sp [1].data.p, sp [2].data.i);
1725                 break;
1726         }
1727         default:
1728                 g_assert_not_reached ();
1729         }
1730
1731         context->env_frame = old_env_frame;
1732         context->current_env = old_env;
1733
1734         return sp;
1735 }
1736
1737 /*
1738  * These functions are the entry points into the interpreter from compiled code.
1739  * They are called by the interp_in wrappers. They have the following signature:
1740  * void (<optional this_arg>, <optional retval pointer>, <arg1>, ..., <argn>, <method ptr>)
1741  * They pack up their arguments into an InterpEntryData structure and call interp_entry ().
1742  * It would be possible for the wrappers to pack up the arguments etc, but that would make them bigger, and there are
1743  * more wrappers then these functions.
1744  * this/static * ret/void * 16 arguments -> 64 functions.
1745  */
1746
1747 #define MAX_INTERP_ENTRY_ARGS 8
1748
1749 #define INTERP_ENTRY_BASE(_method, _this_arg, _res) \
1750         InterpEntryData data; \
1751         (data).rmethod = (_method); \
1752         (data).res = (_res); \
1753         (data).this_arg = (_this_arg); \
1754         (data).many_args = NULL;
1755
1756 #define INTERP_ENTRY0(_this_arg, _res, _method) {       \
1757         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1758         interp_entry (&data); \
1759         }
1760 #define INTERP_ENTRY1(_this_arg, _res, _method) {         \
1761         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1762         (data).args [0] = arg1; \
1763         interp_entry (&data); \
1764         }
1765 #define INTERP_ENTRY2(_this_arg, _res, _method) {  \
1766         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1767         (data).args [0] = arg1; \
1768         (data).args [1] = arg2; \
1769         interp_entry (&data); \
1770         }
1771 #define INTERP_ENTRY3(_this_arg, _res, _method) { \
1772         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1773         (data).args [0] = arg1; \
1774         (data).args [1] = arg2; \
1775         (data).args [2] = arg3; \
1776         interp_entry (&data); \
1777         }
1778 #define INTERP_ENTRY4(_this_arg, _res, _method) {       \
1779         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1780         (data).args [0] = arg1; \
1781         (data).args [1] = arg2; \
1782         (data).args [2] = arg3; \
1783         (data).args [3] = arg4; \
1784         interp_entry (&data); \
1785         }
1786 #define INTERP_ENTRY5(_this_arg, _res, _method) {       \
1787         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1788         (data).args [0] = arg1; \
1789         (data).args [1] = arg2; \
1790         (data).args [2] = arg3; \
1791         (data).args [3] = arg4; \
1792         (data).args [4] = arg5; \
1793         interp_entry (&data); \
1794         }
1795 #define INTERP_ENTRY6(_this_arg, _res, _method) {       \
1796         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1797         (data).args [0] = arg1; \
1798         (data).args [1] = arg2; \
1799         (data).args [2] = arg3; \
1800         (data).args [3] = arg4; \
1801         (data).args [4] = arg5; \
1802         (data).args [5] = arg6; \
1803         interp_entry (&data); \
1804         }
1805 #define INTERP_ENTRY7(_this_arg, _res, _method) {       \
1806         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1807         (data).args [0] = arg1; \
1808         (data).args [1] = arg2; \
1809         (data).args [2] = arg3; \
1810         (data).args [3] = arg4; \
1811         (data).args [4] = arg5; \
1812         (data).args [5] = arg6; \
1813         (data).args [6] = arg7; \
1814         interp_entry (&data); \
1815         }
1816 #define INTERP_ENTRY8(_this_arg, _res, _method) {       \
1817         INTERP_ENTRY_BASE (_method, _this_arg, _res); \
1818         (data).args [0] = arg1; \
1819         (data).args [1] = arg2; \
1820         (data).args [2] = arg3; \
1821         (data).args [3] = arg4; \
1822         (data).args [4] = arg5; \
1823         (data).args [5] = arg6; \
1824         (data).args [6] = arg7; \
1825         (data).args [7] = arg8; \
1826         interp_entry (&data); \
1827         }
1828
1829 #define ARGLIST0 RuntimeMethod *rmethod
1830 #define ARGLIST1 gpointer arg1, RuntimeMethod *rmethod
1831 #define ARGLIST2 gpointer arg1, gpointer arg2, RuntimeMethod *rmethod
1832 #define ARGLIST3 gpointer arg1, gpointer arg2, gpointer arg3, RuntimeMethod *rmethod
1833 #define ARGLIST4 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, RuntimeMethod *rmethod
1834 #define ARGLIST5 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, RuntimeMethod *rmethod
1835 #define ARGLIST6 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, RuntimeMethod *rmethod
1836 #define ARGLIST7 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, RuntimeMethod *rmethod
1837 #define ARGLIST8 gpointer arg1, gpointer arg2, gpointer arg3, gpointer arg4, gpointer arg5, gpointer arg6, gpointer arg7, gpointer arg8, RuntimeMethod *rmethod
1838
1839 static void interp_entry_static_0 (ARGLIST0) INTERP_ENTRY0 (NULL, NULL, rmethod)
1840 static void interp_entry_static_1 (ARGLIST1) INTERP_ENTRY1 (NULL, NULL, rmethod)
1841 static void interp_entry_static_2 (ARGLIST2) INTERP_ENTRY2 (NULL, NULL, rmethod)
1842 static void interp_entry_static_3 (ARGLIST3) INTERP_ENTRY3 (NULL, NULL, rmethod)
1843 static void interp_entry_static_4 (ARGLIST4) INTERP_ENTRY4 (NULL, NULL, rmethod)
1844 static void interp_entry_static_5 (ARGLIST5) INTERP_ENTRY5 (NULL, NULL, rmethod)
1845 static void interp_entry_static_6 (ARGLIST6) INTERP_ENTRY6 (NULL, NULL, rmethod)
1846 static void interp_entry_static_7 (ARGLIST7) INTERP_ENTRY7 (NULL, NULL, rmethod)
1847 static void interp_entry_static_8 (ARGLIST8) INTERP_ENTRY8 (NULL, NULL, rmethod)
1848 static void interp_entry_static_ret_0 (gpointer res, ARGLIST0) INTERP_ENTRY0 (NULL, res, rmethod)
1849 static void interp_entry_static_ret_1 (gpointer res, ARGLIST1) INTERP_ENTRY1 (NULL, res, rmethod)
1850 static void interp_entry_static_ret_2 (gpointer res, ARGLIST2) INTERP_ENTRY2 (NULL, res, rmethod)
1851 static void interp_entry_static_ret_3 (gpointer res, ARGLIST3) INTERP_ENTRY3 (NULL, res, rmethod)
1852 static void interp_entry_static_ret_4 (gpointer res, ARGLIST4) INTERP_ENTRY4 (NULL, res, rmethod)
1853 static void interp_entry_static_ret_5 (gpointer res, ARGLIST5) INTERP_ENTRY5 (NULL, res, rmethod)
1854 static void interp_entry_static_ret_6 (gpointer res, ARGLIST6) INTERP_ENTRY6 (NULL, res, rmethod)
1855 static void interp_entry_static_ret_7 (gpointer res, ARGLIST7) INTERP_ENTRY7 (NULL, res, rmethod)
1856 static void interp_entry_static_ret_8 (gpointer res, ARGLIST8) INTERP_ENTRY8 (NULL, res, rmethod)
1857 static void interp_entry_instance_0 (gpointer this_arg, ARGLIST0) INTERP_ENTRY0 (this_arg, NULL, rmethod)
1858 static void interp_entry_instance_1 (gpointer this_arg, ARGLIST1) INTERP_ENTRY1 (this_arg, NULL, rmethod)
1859 static void interp_entry_instance_2 (gpointer this_arg, ARGLIST2) INTERP_ENTRY2 (this_arg, NULL, rmethod)
1860 static void interp_entry_instance_3 (gpointer this_arg, ARGLIST3) INTERP_ENTRY3 (this_arg, NULL, rmethod)
1861 static void interp_entry_instance_4 (gpointer this_arg, ARGLIST4) INTERP_ENTRY4 (this_arg, NULL, rmethod)
1862 static void interp_entry_instance_5 (gpointer this_arg, ARGLIST5) INTERP_ENTRY5 (this_arg, NULL, rmethod)
1863 static void interp_entry_instance_6 (gpointer this_arg, ARGLIST6) INTERP_ENTRY6 (this_arg, NULL, rmethod)
1864 static void interp_entry_instance_7 (gpointer this_arg, ARGLIST7) INTERP_ENTRY7 (this_arg, NULL, rmethod)
1865 static void interp_entry_instance_8 (gpointer this_arg, ARGLIST8) INTERP_ENTRY8 (this_arg, NULL, rmethod)
1866 static void interp_entry_instance_ret_0 (gpointer this_arg, gpointer res, ARGLIST0) INTERP_ENTRY0 (this_arg, res, rmethod)
1867 static void interp_entry_instance_ret_1 (gpointer this_arg, gpointer res, ARGLIST1) INTERP_ENTRY1 (this_arg, res, rmethod)
1868 static void interp_entry_instance_ret_2 (gpointer this_arg, gpointer res, ARGLIST2) INTERP_ENTRY2 (this_arg, res, rmethod)
1869 static void interp_entry_instance_ret_3 (gpointer this_arg, gpointer res, ARGLIST3) INTERP_ENTRY3 (this_arg, res, rmethod)
1870 static void interp_entry_instance_ret_4 (gpointer this_arg, gpointer res, ARGLIST4) INTERP_ENTRY4 (this_arg, res, rmethod)
1871 static void interp_entry_instance_ret_5 (gpointer this_arg, gpointer res, ARGLIST5) INTERP_ENTRY5 (this_arg, res, rmethod)
1872 static void interp_entry_instance_ret_6 (gpointer this_arg, gpointer res, ARGLIST6) INTERP_ENTRY6 (this_arg, res, rmethod)
1873 static void interp_entry_instance_ret_7 (gpointer this_arg, gpointer res, ARGLIST7) INTERP_ENTRY6 (this_arg, res, rmethod)
1874 static void interp_entry_instance_ret_8 (gpointer this_arg, gpointer res, ARGLIST8) INTERP_ENTRY6 (this_arg, res, rmethod)
1875
1876 #define INTERP_ENTRY_FUNCLIST(type) interp_entry_ ## type ## _0, interp_entry_ ## type ## _1, interp_entry_ ## type ## _2, interp_entry_ ## type ## _3, interp_entry_ ## type ## _4, interp_entry_ ## type ## _5, interp_entry_ ## type ## _6, interp_entry_ ## type ## _7, interp_entry_ ## type ## _8
1877
1878 gpointer entry_funcs_static [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static) };
1879 gpointer entry_funcs_static_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (static_ret) };
1880 gpointer entry_funcs_instance [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance) };
1881 gpointer entry_funcs_instance_ret [MAX_INTERP_ENTRY_ARGS + 1] = { INTERP_ENTRY_FUNCLIST (instance_ret) };
1882
1883 /* General version for methods with more than MAX_INTERP_ENTRY_ARGS arguments */
1884 static void
1885 interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer rmethod)
1886 {
1887         INTERP_ENTRY_BASE (rmethod, this_arg, res);
1888         data.many_args = args;
1889         interp_entry (&data);
1890 }
1891
1892 /*
1893  * mono_interp_create_method_pointer:
1894  *
1895  * Return a function pointer which can be used to call METHOD using the
1896  * interpreter. Return NULL for methods which are not supported.
1897  */
1898 gpointer
1899 mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
1900 {
1901         gpointer addr;
1902         MonoMethodSignature *sig = mono_method_signature (method);
1903         MonoMethod *wrapper;
1904         RuntimeMethod *rmethod;
1905
1906         if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)
1907                 return NULL;
1908
1909         /* HACK: method_ptr of delegate should point to a runtime method*/
1910         if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
1911                 return mono_interp_get_runtime_method (mono_domain_get (), method, error);
1912
1913         rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
1914         if (rmethod->jit_entry)
1915                 return rmethod->jit_entry;
1916         wrapper = mini_get_interp_in_wrapper (sig);
1917
1918         gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, error);
1919         mono_error_assert_ok (error);
1920
1921         //printf ("%s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
1922         gpointer entry_func;
1923         if (sig->param_count > MAX_INTERP_ENTRY_ARGS) {
1924                 entry_func = interp_entry_general;
1925         } else if (sig->hasthis) {
1926                 if (sig->ret->type == MONO_TYPE_VOID)
1927                         entry_func = entry_funcs_instance [sig->param_count];
1928                 else
1929                         entry_func = entry_funcs_instance_ret [sig->param_count];
1930         } else {
1931                 if (sig->ret->type == MONO_TYPE_VOID)
1932                         entry_func = entry_funcs_static [sig->param_count];
1933                 else
1934                         entry_func = entry_funcs_static_ret [sig->param_count];
1935         }
1936         g_assert (entry_func);
1937
1938         /* This is the argument passed to the interp_in wrapper by the static rgctx trampoline */
1939         MonoFtnDesc *ftndesc = g_new0 (MonoFtnDesc, 1);
1940         ftndesc->addr = entry_func;
1941         ftndesc->arg = rmethod;
1942         mono_error_assert_ok (error);
1943
1944         /*
1945          * The wrapper is called by compiled code, which doesn't pass the extra argument, so we pass it in the
1946          * rgctx register using a trampoline.
1947          */
1948
1949         // FIXME: AOT
1950         g_assert (!mono_aot_only);
1951         addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
1952
1953         mono_memory_barrier ();
1954         rmethod->jit_entry = addr;
1955
1956         return addr;
1957 }
1958
1959 #if COUNT_OPS
1960 static int opcode_counts[512];
1961
1962 #define COUNT_OP(op) opcode_counts[op]++
1963 #else
1964 #define COUNT_OP(op) 
1965 #endif
1966
1967 #if DEBUG_INTERP
1968 #define DUMP_INSTR() \
1969         if (tracing > 1) { \
1970                 char *ins; \
1971                 if (sp > frame->stack) { \
1972                         ins = dump_stack (frame->stack, sp); \
1973                 } else { \
1974                         ins = g_strdup (""); \
1975                 } \
1976                 sp->data.l = 0; \
1977                 output_indent (); \
1978                 char *mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
1979                 g_print ("(%p) %s -> ", mono_thread_internal_current (), mn); \
1980                 g_free (mn); \
1981                 mono_interp_dis_mintop(rtm->code, ip); \
1982                 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
1983                 g_free (ins); \
1984         }
1985 #else
1986 #define DUMP_INSTR()
1987 #endif
1988
1989 #ifdef __GNUC__
1990 #define USE_COMPUTED_GOTO 1
1991 #endif
1992 #if USE_COMPUTED_GOTO
1993 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
1994 #define MINT_IN_CASE(x) LAB_ ## x:
1995 #if DEBUG_INTERP
1996 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
1997 #else
1998 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
1999 #endif
2000 #define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
2001 #else
2002 #define MINT_IN_SWITCH(op) switch (op)
2003 #define MINT_IN_CASE(x) case x:
2004 #define MINT_IN_BREAK break
2005 #define MINT_IN_DEFAULT default:
2006 #endif
2007
2008 static void
2009 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
2010
2011 static void 
2012 ves_exec_method_with_context_with_ip (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception)
2013 {
2014         MonoInvocation child_frame;
2015         GSList *finally_ips = NULL;
2016         const unsigned short *endfinally_ip = NULL;
2017         const unsigned short *ip = NULL;
2018         register stackval *sp;
2019         RuntimeMethod *rtm;
2020 #if DEBUG_INTERP
2021         gint tracing = global_tracing;
2022         unsigned char *vtalloc;
2023 #endif
2024         int i32;
2025         unsigned char *vt_sp;
2026         unsigned char *locals;
2027         MonoError error;
2028         MonoObject *o = NULL;
2029         MonoClass *c;
2030 #if USE_COMPUTED_GOTO
2031         static void *in_labels[] = {
2032 #define OPDEF(a,b,c,d) \
2033         &&LAB_ ## a,
2034 #include "mintops.def"
2035         0 };
2036 #endif
2037
2038         frame->ex = NULL;
2039         frame->ex_handler = NULL;
2040         frame->ip = NULL;
2041         context->current_frame = frame;
2042
2043 #if DEBUG_INTERP
2044         debug_enter (frame, &tracing);
2045 #endif
2046
2047         if (!frame->runtime_method->transformed) {
2048                 context->managed_code = 0;
2049 #if DEBUG_INTERP
2050                 char *mn = mono_method_full_name (frame->runtime_method->method, TRUE);
2051                 g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn);
2052                 g_free (mn);
2053 #endif
2054                 frame->ex = mono_interp_transform_method (frame->runtime_method, context);
2055                 context->managed_code = 1;
2056                 if (frame->ex) {
2057                         rtm = NULL;
2058                         ip = NULL;
2059                         goto exit_frame;
2060                 }
2061         }
2062
2063         rtm = frame->runtime_method;
2064         if (!start_with_ip ) {
2065                 frame->args = alloca (rtm->alloca_size);
2066                 memset (frame->args, 0, rtm->alloca_size);
2067
2068                 ip = rtm->code;
2069         } else {
2070                 ip = start_with_ip;
2071         }
2072         sp = frame->stack = (stackval *) ((char *) frame->args + rtm->args_size);
2073         vt_sp = (unsigned char *) sp + rtm->stack_size;
2074 #if DEBUG_INTERP
2075         vtalloc = vt_sp;
2076 #endif
2077         locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
2078         child_frame.parent = frame;
2079
2080         if (filter_exception) {
2081                 sp->data.p = filter_exception;
2082                 sp++;
2083         }
2084
2085         /*
2086          * using while (ip < end) may result in a 15% performance drop, 
2087          * but it may be useful for debug
2088          */
2089         while (1) {
2090         main_loop:
2091                 /* g_assert (sp >= frame->stack); */
2092                 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
2093                 DUMP_INSTR();
2094                 MINT_IN_SWITCH (*ip) {
2095                 MINT_IN_CASE(MINT_INITLOCALS)
2096                         memset (locals, 0, rtm->locals_size);
2097                         ++ip;
2098                         MINT_IN_BREAK;
2099                 MINT_IN_CASE(MINT_NOP)
2100                         ++ip;
2101                         MINT_IN_BREAK;
2102                 MINT_IN_CASE(MINT_BREAK)
2103                         ++ip;
2104                         G_BREAKPOINT (); /* this is not portable... */
2105                         MINT_IN_BREAK;
2106                 MINT_IN_CASE(MINT_LDNULL) 
2107                         sp->data.p = NULL;
2108                         ++ip;
2109                         ++sp;
2110                         MINT_IN_BREAK;
2111                 MINT_IN_CASE(MINT_VTRESULT) {
2112                         int ret_size = * (guint16 *)(ip + 1);
2113                         unsigned char *ret_vt_sp = vt_sp;
2114                         vt_sp -= READ32(ip + 2);
2115                         if (ret_size > 0) {
2116                                 memmove (vt_sp, ret_vt_sp, ret_size);
2117                                 sp [-1].data.p = vt_sp;
2118                                 vt_sp += (ret_size + 7) & ~7;
2119                         }
2120                         ip += 4;
2121                         MINT_IN_BREAK;
2122                 }
2123 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
2124                 MINT_IN_CASE(MINT_LDC_I4_M1)
2125                         LDC(-1);
2126                         MINT_IN_BREAK;
2127                 MINT_IN_CASE(MINT_LDC_I4_0)
2128                         LDC(0);
2129                         MINT_IN_BREAK;
2130                 MINT_IN_CASE(MINT_LDC_I4_1)
2131                         LDC(1);
2132                         MINT_IN_BREAK;
2133                 MINT_IN_CASE(MINT_LDC_I4_2)
2134                         LDC(2);
2135                         MINT_IN_BREAK;
2136                 MINT_IN_CASE(MINT_LDC_I4_3)
2137                         LDC(3);
2138                         MINT_IN_BREAK;
2139                 MINT_IN_CASE(MINT_LDC_I4_4)
2140                         LDC(4);
2141                         MINT_IN_BREAK;
2142                 MINT_IN_CASE(MINT_LDC_I4_5)
2143                         LDC(5);
2144                         MINT_IN_BREAK;
2145                 MINT_IN_CASE(MINT_LDC_I4_6)
2146                         LDC(6);
2147                         MINT_IN_BREAK;
2148                 MINT_IN_CASE(MINT_LDC_I4_7)
2149                         LDC(7);
2150                         MINT_IN_BREAK;
2151                 MINT_IN_CASE(MINT_LDC_I4_8)
2152                         LDC(8);
2153                         MINT_IN_BREAK;
2154                 MINT_IN_CASE(MINT_LDC_I4_S) 
2155                         sp->data.i = *(const short *)(ip + 1);
2156                         ip += 2;
2157                         ++sp;
2158                         MINT_IN_BREAK;
2159                 MINT_IN_CASE(MINT_LDC_I4)
2160                         ++ip;
2161                         sp->data.i = READ32 (ip);
2162                         ip += 2;
2163                         ++sp;
2164                         MINT_IN_BREAK;
2165                 MINT_IN_CASE(MINT_LDC_I8)
2166                         ++ip;
2167                         sp->data.l = READ64 (ip);
2168                         ip += 4;
2169                         ++sp;
2170                         MINT_IN_BREAK;
2171                 MINT_IN_CASE(MINT_LDC_R4) {
2172                         guint32 val;
2173                         ++ip;
2174                         val = READ32(ip);
2175                         sp->data.f = * (float *)&val;
2176                         ip += 2;
2177                         ++sp;
2178                         MINT_IN_BREAK;
2179                 }
2180                 MINT_IN_CASE(MINT_LDC_R8) 
2181                         sp->data.l = READ64 (ip + 1); /* note union usage */
2182                         ip += 5;
2183                         ++sp;
2184                         MINT_IN_BREAK;
2185                 MINT_IN_CASE(MINT_DUP) 
2186                         sp [0] = sp[-1];
2187                         ++sp;
2188                         ++ip; 
2189                         MINT_IN_BREAK;
2190                 MINT_IN_CASE(MINT_DUP_VT)
2191                         i32 = READ32 (ip + 1);
2192                         sp->data.p = vt_sp;
2193                         memcpy(sp->data.p, sp [-1].data.p, i32);
2194                         vt_sp += (i32 + 7) & ~7;
2195                         ++sp;
2196                         ip += 3;
2197                         MINT_IN_BREAK;
2198                 MINT_IN_CASE(MINT_POP) {
2199                         guint16 u16 = (* (guint16 *)(ip + 1)) + 1;
2200                         if (u16 > 1)
2201                                 memmove (sp - u16, sp - 1, (u16 - 1) * sizeof (stackval));
2202                         sp--;
2203                         ip += 2;
2204                         MINT_IN_BREAK;
2205                 }
2206                 MINT_IN_CASE(MINT_JMP) {
2207                         RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
2208                         if (!new_method->transformed) {
2209                                 frame->ip = ip;
2210                                 frame->ex = mono_interp_transform_method (new_method, context);
2211                                 if (frame->ex)
2212                                         goto exit_frame;
2213                         }
2214                         ip += 2;
2215                         if (new_method->alloca_size > rtm->alloca_size)
2216                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
2217                         rtm = frame->runtime_method = new_method;
2218                         vt_sp = (unsigned char *) sp + rtm->stack_size;
2219 #if DEBUG_INTERP
2220                         vtalloc = vt_sp;
2221 #endif
2222                         locals = vt_sp + rtm->vt_stack_size;
2223                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
2224                         MINT_IN_BREAK;
2225                 }
2226                 MINT_IN_CASE(MINT_CALLI) {
2227                         MonoMethodSignature *csignature;
2228                         stackval *endsp = sp;
2229
2230                         frame->ip = ip;
2231                         
2232                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2233                         ip += 2;
2234                         --sp;
2235                         --endsp;
2236                         child_frame.runtime_method = sp->data.p;
2237
2238                         sp->data.p = vt_sp;
2239                         child_frame.retval = sp;
2240                         /* decrement by the actual number of args */
2241                         sp -= csignature->param_count;
2242                         if (csignature->hasthis)
2243                                 --sp;
2244                         child_frame.stack_args = sp;
2245
2246                         /* `this' can be NULL for string:.ctor */
2247                         if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2248                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2249                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2250                         } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2251                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
2252                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2253                         }
2254
2255                         if (csignature->hasthis) {
2256                                 MonoObject *this_arg = sp->data.p;
2257
2258                                 if (this_arg->vtable->klass->valuetype) {
2259                                         gpointer *unboxed = mono_object_unbox (this_arg);
2260                                         sp [0].data.p = unboxed;
2261                                 }
2262                         }
2263
2264                         ves_exec_method_with_context (&child_frame, context);
2265
2266                         context->current_frame = frame;
2267
2268                         if (child_frame.ex) {
2269                                 /*
2270                                  * An exception occurred, need to run finally, fault and catch handlers..
2271                                  */
2272                                 frame->ex = child_frame.ex;
2273                                 goto handle_finally;
2274                         }
2275
2276                         /* need to handle typedbyref ... */
2277                         if (csignature->ret->type != MONO_TYPE_VOID) {
2278                                 *sp = *endsp;
2279                                 sp++;
2280                         }
2281                         MINT_IN_BREAK;
2282                 }
2283                 MINT_IN_CASE(MINT_CALLI_NAT) {
2284                         MonoMethodSignature *csignature;
2285                         stackval *endsp = sp;
2286                         unsigned char *code = NULL;
2287
2288                         frame->ip = ip;
2289                         
2290                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
2291                         ip += 2;
2292                         --sp;
2293                         --endsp;
2294                         code = sp->data.p;
2295                         child_frame.runtime_method = NULL;
2296
2297                         sp->data.p = vt_sp;
2298                         child_frame.retval = sp;
2299                         /* decrement by the actual number of args */
2300                         sp -= csignature->param_count;
2301                         if (csignature->hasthis)
2302                                 --sp;
2303                         child_frame.stack_args = sp;
2304                         ves_pinvoke_method (&child_frame, csignature, (MonoFuncV) code, FALSE, context);
2305
2306                         context->current_frame = frame;
2307
2308                         if (child_frame.ex) {
2309                                 /*
2310                                  * An exception occurred, need to run finally, fault and catch handlers..
2311                                  */
2312                                 frame->ex = child_frame.ex;
2313                                 if (context->search_for_handler) {
2314                                         context->search_for_handler = 0;
2315                                         goto handle_exception;
2316                                 }
2317                                 goto handle_finally;
2318                         }
2319
2320                         /* need to handle typedbyref ... */
2321                         if (csignature->ret->type != MONO_TYPE_VOID) {
2322                                 *sp = *endsp;
2323                                 sp++;
2324                         }
2325                         MINT_IN_BREAK;
2326                 }
2327                 MINT_IN_CASE(MINT_CALL) {
2328                         stackval *endsp = sp;
2329
2330                         frame->ip = ip;
2331                         
2332                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
2333                         ip += 2;
2334                         sp->data.p = vt_sp;
2335                         child_frame.retval = sp;
2336                         /* decrement by the actual number of args */
2337                         sp -= child_frame.runtime_method->param_count;
2338                         if (child_frame.runtime_method->hasthis)
2339                                 --sp;
2340                         child_frame.stack_args = sp;
2341
2342                         /* `this' can be NULL for string:.ctor */
2343                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
2344                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2345                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2346                         }
2347
2348                         ves_exec_method_with_context (&child_frame, context);
2349
2350                         context->current_frame = frame;
2351
2352                         if (child_frame.ex) {
2353                                 /*
2354                                  * An exception occurred, need to run finally, fault and catch handlers..
2355                                  */
2356                                 frame->ex = child_frame.ex;
2357                                 goto handle_exception;;
2358                         }
2359
2360                         /* need to handle typedbyref ... */
2361                         *sp = *endsp;
2362                         sp++;
2363                         MINT_IN_BREAK;
2364                 }
2365                 MINT_IN_CASE(MINT_VCALL) {
2366                         frame->ip = ip;
2367                         
2368                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
2369                         ip += 2;
2370
2371                         sp->data.p = vt_sp;
2372                         child_frame.retval = sp;
2373                         /* decrement by the actual number of args */
2374                         sp -= child_frame.runtime_method->param_count;
2375                         if (child_frame.runtime_method->hasthis) {
2376                                 --sp;
2377                                 MonoObject *this_arg = sp->data.p;
2378                                 if (!this_arg)
2379                                         THROW_EX (mono_get_exception_null_reference(), ip - 2);
2380                         }
2381                         child_frame.stack_args = sp;
2382
2383                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
2384                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2385                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2386                         }
2387
2388                         ves_exec_method_with_context (&child_frame, context);
2389
2390                         context->current_frame = frame;
2391
2392                         if (child_frame.ex) {
2393                                 /*
2394                                  * An exception occurred, need to run finally, fault and catch handlers..
2395                                  */
2396                                 frame->ex = child_frame.ex;
2397                                 goto handle_finally;
2398                         }
2399                         MINT_IN_BREAK;
2400                 }
2401
2402                 MINT_IN_CASE(MINT_JIT_CALL) {
2403                         MonoMethodSignature *sig;
2404                         RuntimeMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
2405                         MonoFtnDesc ftndesc;
2406                         guint8 res_buf [256];
2407                         MonoType *type;
2408
2409                         //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
2410
2411                         /*
2412                          * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
2413                          * by ref and return a return value using an explicit return value argument.
2414                          */
2415                         if (!rmethod->jit_wrapper) {
2416                                 MonoMethod *method = rmethod->method;
2417                                 MonoError error;
2418
2419                                 sig = mono_method_signature (method);
2420                                 g_assert (sig);
2421
2422                                 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2423                                 //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
2424
2425                                 gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
2426                                 mono_error_assert_ok (&error);
2427
2428                                 gpointer addr = mono_jit_compile_method_jit_only (method, &error);
2429                                 g_assert (addr);
2430                                 mono_error_assert_ok (&error);
2431
2432                                 rmethod->jit_addr = addr;
2433                                 rmethod->jit_sig = sig;
2434                                 mono_memory_barrier ();
2435                                 rmethod->jit_wrapper = jit_wrapper;
2436
2437                         } else {
2438                                 sig = rmethod->jit_sig;
2439                         }
2440
2441                         frame->ip = ip;
2442                         ip += 2;
2443                         sp -= sig->param_count;
2444                         if (sig->hasthis)
2445                                 --sp;
2446
2447                         ftndesc.addr = rmethod->jit_addr;
2448                         ftndesc.arg = NULL;
2449
2450                         // FIXME: Optimize this
2451
2452                         gpointer args [32];
2453                         int pindex = 0;
2454                         int stack_index = 0;
2455                         if (rmethod->hasthis) {
2456                                 args [pindex ++] = sp [0].data.p;
2457                                 stack_index ++;
2458                         }
2459                         type = rmethod->rtype;
2460                         if (type->type != MONO_TYPE_VOID) {
2461                                 if (MONO_TYPE_ISSTRUCT (type))
2462                                         args [pindex ++] = vt_sp;
2463                                 else
2464                                         args [pindex ++] = res_buf;
2465                         }
2466                         for (int i = 0; i < rmethod->param_count; ++i) {
2467                                 MonoType *t = rmethod->param_types [i];
2468                                 stackval *sval = &sp [stack_index + i];
2469                                 if (sig->params [i]->byref) {
2470                                         args [pindex ++] = sval->data.p;
2471                                 } else if (MONO_TYPE_ISSTRUCT (t)) {
2472                                         args [pindex ++] = sval->data.p;
2473                                 } else if (MONO_TYPE_IS_REFERENCE (t)) {
2474                                         args [pindex ++] = &sval->data.p;
2475                                 } else {
2476                                         switch (t->type) {
2477                                         case MONO_TYPE_I1:
2478                                         case MONO_TYPE_U1:
2479                                         case MONO_TYPE_I2:
2480                                         case MONO_TYPE_U2:
2481                                         case MONO_TYPE_I4:
2482                                         case MONO_TYPE_U4:
2483                                         case MONO_TYPE_VALUETYPE:
2484                                                 args [pindex ++] = &sval->data.i;
2485                                                 break;
2486                                         case MONO_TYPE_PTR:
2487                                         case MONO_TYPE_FNPTR:
2488                                         case MONO_TYPE_I:
2489                                         case MONO_TYPE_U:
2490                                         case MONO_TYPE_OBJECT:
2491                                                 args [pindex ++] = &sval->data.p;
2492                                                 break;
2493                                         case MONO_TYPE_I8:
2494                                         case MONO_TYPE_U8:
2495                                                 args [pindex ++] = &sval->data.l;
2496                                                 break;
2497                                         default:
2498                                                 printf ("%s\n", mono_type_full_name (t));
2499                                                 g_assert_not_reached ();
2500                                         }
2501                                 }
2502                         }
2503
2504                         switch (pindex) {
2505                         case 0: {
2506                                 void (*func)(gpointer) = rmethod->jit_wrapper;
2507
2508                                 func (&ftndesc);
2509                                 break;
2510                         }
2511                         case 1: {
2512                                 void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
2513
2514                                 func (args [0], &ftndesc);
2515                                 break;
2516                         }
2517                         case 2: {
2518                                 void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2519
2520                                 func (args [0], args [1], &ftndesc);
2521                                 break;
2522                         }
2523                         case 3: {
2524                                 void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2525
2526                                 func (args [0], args [1], args [2], &ftndesc);
2527                                 break;
2528                         }
2529                         case 4: {
2530                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2531
2532                                 func (args [0], args [1], args [2], args [3], &ftndesc);
2533                                 break;
2534                         }
2535                         case 5: {
2536                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2537
2538                                 func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
2539                                 break;
2540                         }
2541                         case 6: {
2542                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2543
2544                                 func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
2545                                 break;
2546                         }
2547                         case 7: {
2548                                 void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
2549
2550                                 func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
2551                                 break;
2552                         }
2553                         default:
2554                                 g_assert_not_reached ();
2555                                 break;
2556                         }
2557
2558                         MonoType *rtype = rmethod->rtype;
2559                         switch (rtype->type) {
2560                         case MONO_TYPE_VOID:
2561                         case MONO_TYPE_OBJECT:
2562                         case MONO_TYPE_STRING:
2563                         case MONO_TYPE_CLASS:
2564                         case MONO_TYPE_ARRAY:
2565                         case MONO_TYPE_SZARRAY:
2566                         case MONO_TYPE_I:
2567                         case MONO_TYPE_U:
2568                                 sp->data.p = *(gpointer*)res_buf;
2569                                 break;
2570                         case MONO_TYPE_I1:
2571                                 sp->data.i = *(gint8*)res_buf;
2572                                 break;
2573                         case MONO_TYPE_U1:
2574                                 sp->data.i = *(guint8*)res_buf;
2575                                 break;
2576                         case MONO_TYPE_I2:
2577                                 sp->data.i = *(gint16*)res_buf;
2578                                 break;
2579                         case MONO_TYPE_U2:
2580                                 sp->data.i = *(guint16*)res_buf;
2581                                 break;
2582                         case MONO_TYPE_I4:
2583                                 sp->data.i = *(gint32*)res_buf;
2584                                 break;
2585                         case MONO_TYPE_U4:
2586                                 sp->data.i = *(guint32*)res_buf;
2587                                 break;
2588                         case MONO_TYPE_VALUETYPE:
2589                                 /* The result was written to vt_sp */
2590                                 sp->data.p = vt_sp;
2591                                 break;
2592                         case MONO_TYPE_GENERICINST:
2593                                 if (MONO_TYPE_IS_REFERENCE (rtype)) {
2594                                         sp->data.p = *(gpointer*)res_buf;
2595                                 } else {
2596                                         /* The result was written to vt_sp */
2597                                         sp->data.p = vt_sp;
2598                                 }
2599                                 break;
2600                         default:
2601                                 printf ("%s\n", mono_type_full_name (rtype));
2602                                 g_assert_not_reached ();
2603                                 break;
2604                         }
2605                         if (rtype->type != MONO_TYPE_VOID)
2606                                 sp++;
2607                         MINT_IN_BREAK;
2608                 }
2609
2610                 MINT_IN_CASE(MINT_CALLVIRT) {
2611                         stackval *endsp = sp;
2612                         MonoObject *this_arg;
2613                         guint32 token;
2614
2615                         frame->ip = ip;
2616                         
2617                         token = * (unsigned short *)(ip + 1);
2618                         ip += 2;
2619                         child_frame.runtime_method = rtm->data_items [token];
2620                         sp->data.p = vt_sp;
2621                         child_frame.retval = sp;
2622
2623                         /* decrement by the actual number of args */
2624                         sp -= child_frame.runtime_method->param_count + 1;
2625                         child_frame.stack_args = sp;
2626                         this_arg = sp->data.p;
2627                         if (!this_arg)
2628                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2629                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2630
2631                         MonoClass *this_class = this_arg->vtable->klass;
2632                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2633                                 /* unbox */
2634                                 gpointer *unboxed = mono_object_unbox (this_arg);
2635                                 sp [0].data.p = unboxed;
2636                         }
2637
2638                         ves_exec_method_with_context (&child_frame, context);
2639
2640                         context->current_frame = frame;
2641
2642                         if (child_frame.ex) {
2643                                 /*
2644                                  * An exception occurred, need to run finally, fault and catch handlers..
2645                                  */
2646                                 frame->ex = child_frame.ex;
2647                                 if (context->search_for_handler) {
2648                                         context->search_for_handler = 0;
2649                                         goto handle_exception;
2650                                 }
2651                                 goto handle_finally;
2652                         }
2653
2654                         /* need to handle typedbyref ... */
2655                         *sp = *endsp;
2656                         sp++;
2657                         MINT_IN_BREAK;
2658                 }
2659                 MINT_IN_CASE(MINT_VCALLVIRT) {
2660                         MonoObject *this_arg;
2661                         guint32 token;
2662
2663                         frame->ip = ip;
2664                         
2665                         token = * (unsigned short *)(ip + 1);
2666                         ip += 2;
2667                         child_frame.runtime_method = rtm->data_items [token];
2668                         sp->data.p = vt_sp;
2669                         child_frame.retval = sp;
2670
2671                         /* decrement by the actual number of args */
2672                         sp -= child_frame.runtime_method->param_count + 1;
2673                         child_frame.stack_args = sp;
2674                         this_arg = sp->data.p;
2675                         if (!this_arg)
2676                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2677                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2678
2679                         MonoClass *this_class = this_arg->vtable->klass;
2680                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2681                                 gpointer *unboxed = mono_object_unbox (this_arg);
2682                                 sp [0].data.p = unboxed;
2683                         }
2684
2685                         ves_exec_method_with_context (&child_frame, context);
2686
2687                         context->current_frame = frame;
2688
2689                         if (child_frame.ex) {
2690                                 /*
2691                                  * An exception occurred, need to run finally, fault and catch handlers..
2692                                  */
2693                                 frame->ex = child_frame.ex;
2694                                 if (context->search_for_handler) {
2695                                         context->search_for_handler = 0;
2696                                         goto handle_exception;
2697                                 }
2698                                 goto handle_finally;
2699                         }
2700                         MINT_IN_BREAK;
2701                 }
2702                 MINT_IN_CASE(MINT_CALLRUN)
2703                         ves_runtime_method (frame, context);
2704                         if (frame->ex) {
2705                                 rtm = NULL;
2706                                 goto handle_exception;
2707                         }
2708                         goto exit_frame;
2709                 MINT_IN_CASE(MINT_RET)
2710                         --sp;
2711                         *frame->retval = *sp;
2712                         if (sp > frame->stack)
2713                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
2714                         goto exit_frame;
2715                 MINT_IN_CASE(MINT_RET_VOID)
2716                         if (sp > frame->stack)
2717                                 g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
2718                         goto exit_frame;
2719                 MINT_IN_CASE(MINT_RET_VT)
2720                         i32 = READ32(ip + 1);
2721                         --sp;
2722                         memcpy(frame->retval->data.p, sp->data.p, i32);
2723                         if (sp > frame->stack)
2724                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
2725                         goto exit_frame;
2726                 MINT_IN_CASE(MINT_BR_S)
2727                         ip += (short) *(ip + 1);
2728                         MINT_IN_BREAK;
2729                 MINT_IN_CASE(MINT_BR)
2730                         ip += (gint32) READ32(ip + 1);
2731                         MINT_IN_BREAK;
2732 #define ZEROP_S(datamem, op) \
2733         --sp; \
2734         if (sp->data.datamem op 0) \
2735                 ip += * (gint16 *)(ip + 1); \
2736         else \
2737                 ip += 2;
2738
2739 #define ZEROP(datamem, op) \
2740         --sp; \
2741         if (sp->data.datamem op 0) \
2742                 ip += READ32(ip + 1); \
2743         else \
2744                 ip += 3;
2745
2746                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
2747                         ZEROP_S(i, ==);
2748                         MINT_IN_BREAK;
2749                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
2750                         ZEROP_S(l, ==);
2751                         MINT_IN_BREAK;
2752                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
2753                         ZEROP_S(f, ==);
2754                         MINT_IN_BREAK;
2755                 MINT_IN_CASE(MINT_BRFALSE_I4)
2756                         ZEROP(i, ==);
2757                         MINT_IN_BREAK;
2758                 MINT_IN_CASE(MINT_BRFALSE_I8)
2759                         ZEROP(l, ==);
2760                         MINT_IN_BREAK;
2761                 MINT_IN_CASE(MINT_BRFALSE_R8)
2762                         ZEROP_S(f, ==);
2763                         MINT_IN_BREAK;
2764                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
2765                         ZEROP_S(i, !=);
2766                         MINT_IN_BREAK;
2767                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
2768                         ZEROP_S(l, !=);
2769                         MINT_IN_BREAK;
2770                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
2771                         ZEROP_S(f, !=);
2772                         MINT_IN_BREAK;
2773                 MINT_IN_CASE(MINT_BRTRUE_I4)
2774                         ZEROP(i, !=);
2775                         MINT_IN_BREAK;
2776                 MINT_IN_CASE(MINT_BRTRUE_I8)
2777                         ZEROP(l, !=);
2778                         MINT_IN_BREAK;
2779                 MINT_IN_CASE(MINT_BRTRUE_R8)
2780                         ZEROP(f, !=);
2781                         MINT_IN_BREAK;
2782 #define CONDBR_S(cond) \
2783         sp -= 2; \
2784         if (cond) \
2785                 ip += * (gint16 *)(ip + 1); \
2786         else \
2787                 ip += 2;
2788 #define BRELOP_S(datamem, op) \
2789         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
2790
2791 #define CONDBR(cond) \
2792         sp -= 2; \
2793         if (cond) \
2794                 ip += READ32(ip + 1); \
2795         else \
2796                 ip += 3;
2797
2798 #define BRELOP(datamem, op) \
2799         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
2800
2801                 MINT_IN_CASE(MINT_BEQ_I4_S)
2802                         BRELOP_S(i, ==)
2803                         MINT_IN_BREAK;
2804                 MINT_IN_CASE(MINT_BEQ_I8_S)
2805                         BRELOP_S(l, ==)
2806                         MINT_IN_BREAK;
2807                 MINT_IN_CASE(MINT_BEQ_R8_S)
2808                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2809                         MINT_IN_BREAK;
2810                 MINT_IN_CASE(MINT_BEQ_I4)
2811                         BRELOP(i, ==)
2812                         MINT_IN_BREAK;
2813                 MINT_IN_CASE(MINT_BEQ_I8)
2814                         BRELOP(l, ==)
2815                         MINT_IN_BREAK;
2816                 MINT_IN_CASE(MINT_BEQ_R8)
2817                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2818                         MINT_IN_BREAK;
2819                 MINT_IN_CASE(MINT_BGE_I4_S)
2820                         BRELOP_S(i, >=)
2821                         MINT_IN_BREAK;
2822                 MINT_IN_CASE(MINT_BGE_I8_S)
2823                         BRELOP_S(l, >=)
2824                         MINT_IN_BREAK;
2825                 MINT_IN_CASE(MINT_BGE_R8_S)
2826                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2827                         MINT_IN_BREAK;
2828                 MINT_IN_CASE(MINT_BGE_I4)
2829                         BRELOP(i, >=)
2830                         MINT_IN_BREAK;
2831                 MINT_IN_CASE(MINT_BGE_I8)
2832                         BRELOP(l, >=)
2833                         MINT_IN_BREAK;
2834                 MINT_IN_CASE(MINT_BGE_R8)
2835                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2836                         MINT_IN_BREAK;
2837                 MINT_IN_CASE(MINT_BGT_I4_S)
2838                         BRELOP_S(i, >)
2839                         MINT_IN_BREAK;
2840                 MINT_IN_CASE(MINT_BGT_I8_S)
2841                         BRELOP_S(l, >)
2842                         MINT_IN_BREAK;
2843                 MINT_IN_CASE(MINT_BGT_R8_S)
2844                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2845                         MINT_IN_BREAK;
2846                 MINT_IN_CASE(MINT_BGT_I4)
2847                         BRELOP(i, >)
2848                         MINT_IN_BREAK;
2849                 MINT_IN_CASE(MINT_BGT_I8)
2850                         BRELOP(l, >)
2851                         MINT_IN_BREAK;
2852                 MINT_IN_CASE(MINT_BGT_R8)
2853                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2854                         MINT_IN_BREAK;
2855                 MINT_IN_CASE(MINT_BLT_I4_S)
2856                         BRELOP_S(i, <)
2857                         MINT_IN_BREAK;
2858                 MINT_IN_CASE(MINT_BLT_I8_S)
2859                         BRELOP_S(l, <)
2860                         MINT_IN_BREAK;
2861                 MINT_IN_CASE(MINT_BLT_R8_S)
2862                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2863                         MINT_IN_BREAK;
2864                 MINT_IN_CASE(MINT_BLT_I4)
2865                         BRELOP(i, <)
2866                         MINT_IN_BREAK;
2867                 MINT_IN_CASE(MINT_BLT_I8)
2868                         BRELOP(l, <)
2869                         MINT_IN_BREAK;
2870                 MINT_IN_CASE(MINT_BLT_R8)
2871                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2872                         MINT_IN_BREAK;
2873                 MINT_IN_CASE(MINT_BLE_I4_S)
2874                         BRELOP_S(i, <=)
2875                         MINT_IN_BREAK;
2876                 MINT_IN_CASE(MINT_BLE_I8_S)
2877                         BRELOP_S(l, <=)
2878                         MINT_IN_BREAK;
2879                 MINT_IN_CASE(MINT_BLE_R8_S)
2880                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2881                         MINT_IN_BREAK;
2882                 MINT_IN_CASE(MINT_BLE_I4)
2883                         BRELOP(i, <=)
2884                         MINT_IN_BREAK;
2885                 MINT_IN_CASE(MINT_BLE_I8)
2886                         BRELOP(l, <=)
2887                         MINT_IN_BREAK;
2888                 MINT_IN_CASE(MINT_BLE_R8)
2889                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2890                         MINT_IN_BREAK;
2891                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
2892                         BRELOP_S(i, !=)
2893                         MINT_IN_BREAK;
2894                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
2895                         BRELOP_S(l, !=)
2896                         MINT_IN_BREAK;
2897                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
2898                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
2899                         MINT_IN_BREAK;
2900                 MINT_IN_CASE(MINT_BNE_UN_I4)
2901                         BRELOP(i, !=)
2902                         MINT_IN_BREAK;
2903                 MINT_IN_CASE(MINT_BNE_UN_I8)
2904                         BRELOP(l, !=)
2905                         MINT_IN_BREAK;
2906                 MINT_IN_CASE(MINT_BNE_UN_R8)
2907                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
2908                         MINT_IN_BREAK;
2909
2910 #define BRELOP_S_CAST(datamem, op, type) \
2911         sp -= 2; \
2912         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2913                 ip += * (gint16 *)(ip + 1); \
2914         else \
2915                 ip += 2;
2916
2917 #define BRELOP_CAST(datamem, op, type) \
2918         sp -= 2; \
2919         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2920                 ip += READ32(ip + 1); \
2921         else \
2922                 ip += 3;
2923
2924                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
2925                         BRELOP_S_CAST(i, >=, guint32);
2926                         MINT_IN_BREAK;
2927                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
2928                         BRELOP_S_CAST(l, >=, guint64);
2929                         MINT_IN_BREAK;
2930                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
2931                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2932                         MINT_IN_BREAK;
2933                 MINT_IN_CASE(MINT_BGE_UN_I4)
2934                         BRELOP_CAST(i, >=, guint32);
2935                         MINT_IN_BREAK;
2936                 MINT_IN_CASE(MINT_BGE_UN_I8)
2937                         BRELOP_CAST(l, >=, guint64);
2938                         MINT_IN_BREAK;
2939                 MINT_IN_CASE(MINT_BGE_UN_R8)
2940                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2941                         MINT_IN_BREAK;
2942                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
2943                         BRELOP_S_CAST(i, >, guint32);
2944                         MINT_IN_BREAK;
2945                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
2946                         BRELOP_S_CAST(l, >, guint64);
2947                         MINT_IN_BREAK;
2948                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
2949                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2950                         MINT_IN_BREAK;
2951                 MINT_IN_CASE(MINT_BGT_UN_I4)
2952                         BRELOP_CAST(i, >, guint32);
2953                         MINT_IN_BREAK;
2954                 MINT_IN_CASE(MINT_BGT_UN_I8)
2955                         BRELOP_CAST(l, >, guint64);
2956                         MINT_IN_BREAK;
2957                 MINT_IN_CASE(MINT_BGT_UN_R8)
2958                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2959                         MINT_IN_BREAK;
2960                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
2961                         BRELOP_S_CAST(i, <=, guint32);
2962                         MINT_IN_BREAK;
2963                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
2964                         BRELOP_S_CAST(l, <=, guint64);
2965                         MINT_IN_BREAK;
2966                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
2967                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2968                         MINT_IN_BREAK;
2969                 MINT_IN_CASE(MINT_BLE_UN_I4)
2970                         BRELOP_CAST(i, <=, guint32);
2971                         MINT_IN_BREAK;
2972                 MINT_IN_CASE(MINT_BLE_UN_I8)
2973                         BRELOP_CAST(l, <=, guint64);
2974                         MINT_IN_BREAK;
2975                 MINT_IN_CASE(MINT_BLE_UN_R8)
2976                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2977                         MINT_IN_BREAK;
2978                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
2979                         BRELOP_S_CAST(i, <, guint32);
2980                         MINT_IN_BREAK;
2981                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
2982                         BRELOP_S_CAST(l, <, guint64);
2983                         MINT_IN_BREAK;
2984                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
2985                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2986                         MINT_IN_BREAK;
2987                 MINT_IN_CASE(MINT_BLT_UN_I4)
2988                         BRELOP_CAST(i, <, guint32);
2989                         MINT_IN_BREAK;
2990                 MINT_IN_CASE(MINT_BLT_UN_I8)
2991                         BRELOP_CAST(l, <, guint64);
2992                         MINT_IN_BREAK;
2993                 MINT_IN_CASE(MINT_BLT_UN_R8)
2994                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2995                         MINT_IN_BREAK;
2996                 MINT_IN_CASE(MINT_SWITCH) {
2997                         guint32 n;
2998                         const unsigned short *st;
2999                         ++ip;
3000                         n = READ32 (ip);
3001                         ip += 2;
3002                         st = ip + 2 * n;
3003                         --sp;
3004                         if ((guint32)sp->data.i < n) {
3005                                 gint offset;
3006                                 ip += 2 * (guint32)sp->data.i;
3007                                 offset = READ32 (ip);
3008                                 ip = st + offset;
3009                         } else {
3010                                 ip = st;
3011                         }
3012                         MINT_IN_BREAK;
3013                 }
3014                 MINT_IN_CASE(MINT_LDIND_I1)
3015                         ++ip;
3016                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
3017                         MINT_IN_BREAK;
3018                 MINT_IN_CASE(MINT_LDIND_U1)
3019                         ++ip;
3020                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
3021                         MINT_IN_BREAK;
3022                 MINT_IN_CASE(MINT_LDIND_I2)
3023                         ++ip;
3024                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
3025                         MINT_IN_BREAK;
3026                 MINT_IN_CASE(MINT_LDIND_U2)
3027                         ++ip;
3028                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
3029                         MINT_IN_BREAK;
3030                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
3031                 MINT_IN_CASE(MINT_LDIND_U4)
3032                         ++ip;
3033                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
3034                         MINT_IN_BREAK;
3035                 MINT_IN_CASE(MINT_LDIND_I8)
3036                         ++ip;
3037                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
3038                         MINT_IN_BREAK;
3039                 MINT_IN_CASE(MINT_LDIND_I) {
3040                         guint16 offset = * (guint16 *)(ip + 1);
3041                         sp[-1 - offset].data.p = *(gpointer*)sp[-1 - offset].data.p;
3042                         ip += 2;
3043                         MINT_IN_BREAK;
3044                 }
3045                 MINT_IN_CASE(MINT_LDIND_R4)
3046                         ++ip;
3047                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
3048                         MINT_IN_BREAK;
3049                 MINT_IN_CASE(MINT_LDIND_R8)
3050                         ++ip;
3051                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
3052                         MINT_IN_BREAK;
3053                 MINT_IN_CASE(MINT_LDIND_REF)
3054                         ++ip;
3055                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
3056                         MINT_IN_BREAK;
3057                 MINT_IN_CASE(MINT_STIND_REF) 
3058                         ++ip;
3059                         sp -= 2;
3060                         mono_gc_wbarrier_generic_store (sp->data.p, sp [1].data.p);
3061                         MINT_IN_BREAK;
3062                 MINT_IN_CASE(MINT_STIND_I1)
3063                         ++ip;
3064                         sp -= 2;
3065                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
3066                         MINT_IN_BREAK;
3067                 MINT_IN_CASE(MINT_STIND_I2)
3068                         ++ip;
3069                         sp -= 2;
3070                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
3071                         MINT_IN_BREAK;
3072                 MINT_IN_CASE(MINT_STIND_I4)
3073                         ++ip;
3074                         sp -= 2;
3075                         * (gint32 *) sp->data.p = sp[1].data.i;
3076                         MINT_IN_BREAK;
3077                 MINT_IN_CASE(MINT_STIND_I)
3078                         ++ip;
3079                         sp -= 2;
3080                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
3081                         MINT_IN_BREAK;
3082                 MINT_IN_CASE(MINT_STIND_I8)
3083                         ++ip;
3084                         sp -= 2;
3085                         * (gint64 *) sp->data.p = sp[1].data.l;
3086                         MINT_IN_BREAK;
3087                 MINT_IN_CASE(MINT_STIND_R4)
3088                         ++ip;
3089                         sp -= 2;
3090                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
3091                         MINT_IN_BREAK;
3092                 MINT_IN_CASE(MINT_STIND_R8)
3093                         ++ip;
3094                         sp -= 2;
3095                         * (double *) sp->data.p = sp[1].data.f;
3096                         MINT_IN_BREAK;
3097 #define BINOP(datamem, op) \
3098         --sp; \
3099         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
3100         ++ip;
3101                 MINT_IN_CASE(MINT_ADD_I4)
3102                         BINOP(i, +);
3103                         MINT_IN_BREAK;
3104                 MINT_IN_CASE(MINT_ADD_I8)
3105                         BINOP(l, +);
3106                         MINT_IN_BREAK;
3107                 MINT_IN_CASE(MINT_ADD_R8)
3108                         BINOP(f, +);
3109                         MINT_IN_BREAK;
3110                 MINT_IN_CASE(MINT_ADD1_I4)
3111                         ++sp [-1].data.i;
3112                         ++ip;
3113                         MINT_IN_BREAK;
3114                 MINT_IN_CASE(MINT_SUB_I4)
3115                         BINOP(i, -);
3116                         MINT_IN_BREAK;
3117                 MINT_IN_CASE(MINT_SUB_I8)
3118                         BINOP(l, -);
3119                         MINT_IN_BREAK;
3120                 MINT_IN_CASE(MINT_SUB_R8)
3121                         BINOP(f, -);
3122                         MINT_IN_BREAK;
3123                 MINT_IN_CASE(MINT_SUB1_I4)
3124                         --sp [-1].data.i;
3125                         ++ip;
3126                         MINT_IN_BREAK;
3127                 MINT_IN_CASE(MINT_MUL_I4)
3128                         BINOP(i, *);
3129                         MINT_IN_BREAK;
3130                 MINT_IN_CASE(MINT_MUL_I8)
3131                         BINOP(l, *);
3132                         MINT_IN_BREAK;
3133                 MINT_IN_CASE(MINT_MUL_R8)
3134                         BINOP(f, *);
3135                         MINT_IN_BREAK;
3136                 MINT_IN_CASE(MINT_DIV_I4)
3137                         if (sp [-1].data.i == 0)
3138                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3139                         if (sp [-1].data.i == (-1))
3140                                 THROW_EX (mono_get_exception_overflow (), ip);
3141                         BINOP(i, /);
3142                         MINT_IN_BREAK;
3143                 MINT_IN_CASE(MINT_DIV_I8)
3144                         if (sp [-1].data.l == 0)
3145                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3146                         if (sp [-1].data.l == (-1))
3147                                 THROW_EX (mono_get_exception_overflow (), ip);
3148                         BINOP(l, /);
3149                         MINT_IN_BREAK;
3150                 MINT_IN_CASE(MINT_DIV_R8)
3151                         BINOP(f, /);
3152                         MINT_IN_BREAK;
3153
3154 #define BINOP_CAST(datamem, op, type) \
3155         --sp; \
3156         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3157         ++ip;
3158                 MINT_IN_CASE(MINT_DIV_UN_I4)
3159                         if (sp [-1].data.i == 0)
3160                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3161                         BINOP_CAST(i, /, guint32);
3162                         MINT_IN_BREAK;
3163                 MINT_IN_CASE(MINT_DIV_UN_I8)
3164                         if (sp [-1].data.l == 0)
3165                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3166                         BINOP_CAST(l, /, guint64);
3167                         MINT_IN_BREAK;
3168                 MINT_IN_CASE(MINT_REM_I4)
3169                         if (sp [-1].data.i == 0)
3170                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3171                         if (sp [-1].data.i == (-1))
3172                                 THROW_EX (mono_get_exception_overflow (), ip);
3173                         BINOP(i, %);
3174                         MINT_IN_BREAK;
3175                 MINT_IN_CASE(MINT_REM_I8)
3176                         if (sp [-1].data.l == 0)
3177                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3178                         if (sp [-1].data.l == (-1))
3179                                 THROW_EX (mono_get_exception_overflow (), ip);
3180                         BINOP(l, %);
3181                         MINT_IN_BREAK;
3182                 MINT_IN_CASE(MINT_REM_R8)
3183                         /* FIXME: what do we actually do here? */
3184                         --sp;
3185                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
3186                         ++ip;
3187                         MINT_IN_BREAK;
3188                 MINT_IN_CASE(MINT_REM_UN_I4)
3189                         if (sp [-1].data.i == 0)
3190                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3191                         BINOP_CAST(i, %, guint32);
3192                         MINT_IN_BREAK;
3193                 MINT_IN_CASE(MINT_REM_UN_I8)
3194                         if (sp [-1].data.l == 0)
3195                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
3196                         BINOP_CAST(l, %, guint64);
3197                         MINT_IN_BREAK;
3198                 MINT_IN_CASE(MINT_AND_I4)
3199                         BINOP(i, &);
3200                         MINT_IN_BREAK;
3201                 MINT_IN_CASE(MINT_AND_I8)
3202                         BINOP(l, &);
3203                         MINT_IN_BREAK;
3204                 MINT_IN_CASE(MINT_OR_I4)
3205                         BINOP(i, |);
3206                         MINT_IN_BREAK;
3207                 MINT_IN_CASE(MINT_OR_I8)
3208                         BINOP(l, |);
3209                         MINT_IN_BREAK;
3210                 MINT_IN_CASE(MINT_XOR_I4)
3211                         BINOP(i, ^);
3212                         MINT_IN_BREAK;
3213                 MINT_IN_CASE(MINT_XOR_I8)
3214                         BINOP(l, ^);
3215                         MINT_IN_BREAK;
3216
3217 #define SHIFTOP(datamem, op) \
3218         --sp; \
3219         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
3220         ++ip;
3221
3222                 MINT_IN_CASE(MINT_SHL_I4)
3223                         SHIFTOP(i, <<);
3224                         MINT_IN_BREAK;
3225                 MINT_IN_CASE(MINT_SHL_I8)
3226                         SHIFTOP(l, <<);
3227                         MINT_IN_BREAK;
3228                 MINT_IN_CASE(MINT_SHR_I4)
3229                         SHIFTOP(i, >>);
3230                         MINT_IN_BREAK;
3231                 MINT_IN_CASE(MINT_SHR_I8)
3232                         SHIFTOP(l, >>);
3233                         MINT_IN_BREAK;
3234                 MINT_IN_CASE(MINT_SHR_UN_I4)
3235                         --sp;
3236                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
3237                         ++ip;
3238                         MINT_IN_BREAK;
3239                 MINT_IN_CASE(MINT_SHR_UN_I8)
3240                         --sp;
3241                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
3242                         ++ip;
3243                         MINT_IN_BREAK;
3244                 MINT_IN_CASE(MINT_NEG_I4)
3245                         sp [-1].data.i = - sp [-1].data.i;
3246                         ++ip;
3247                         MINT_IN_BREAK;
3248                 MINT_IN_CASE(MINT_NEG_I8)
3249                         sp [-1].data.l = - sp [-1].data.l;
3250                         ++ip;
3251                         MINT_IN_BREAK;
3252                 MINT_IN_CASE(MINT_NEG_R8)
3253                         sp [-1].data.f = - sp [-1].data.f;
3254                         ++ip;
3255                         MINT_IN_BREAK;
3256                 MINT_IN_CASE(MINT_NOT_I4)
3257                         sp [-1].data.i = ~ sp [-1].data.i;
3258                         ++ip;
3259                         MINT_IN_BREAK;
3260                 MINT_IN_CASE(MINT_NOT_I8)
3261                         sp [-1].data.l = ~ sp [-1].data.l;
3262                         ++ip;
3263                         MINT_IN_BREAK;
3264                 MINT_IN_CASE(MINT_CONV_I1_I4)
3265                         sp [-1].data.i = (gint8)sp [-1].data.i;
3266                         ++ip;
3267                         MINT_IN_BREAK;
3268                 MINT_IN_CASE(MINT_CONV_I1_I8)
3269                         sp [-1].data.i = (gint8)sp [-1].data.l;
3270                         ++ip;
3271                         MINT_IN_BREAK;
3272                 MINT_IN_CASE(MINT_CONV_I1_R8)
3273                         sp [-1].data.i = (gint8)sp [-1].data.f;
3274                         ++ip;
3275                         MINT_IN_BREAK;
3276                 MINT_IN_CASE(MINT_CONV_U1_I4)
3277                         sp [-1].data.i = (guint8)sp [-1].data.i;
3278                         ++ip;
3279                         MINT_IN_BREAK;
3280                 MINT_IN_CASE(MINT_CONV_U1_I8)
3281                         sp [-1].data.i = (guint8)sp [-1].data.l;
3282                         ++ip;
3283                         MINT_IN_BREAK;
3284                 MINT_IN_CASE(MINT_CONV_U1_R8)
3285                         sp [-1].data.i = (guint8)sp [-1].data.f;
3286                         ++ip;
3287                         MINT_IN_BREAK;
3288                 MINT_IN_CASE(MINT_CONV_I2_I4)
3289                         sp [-1].data.i = (gint16)sp [-1].data.i;
3290                         ++ip;
3291                         MINT_IN_BREAK;
3292                 MINT_IN_CASE(MINT_CONV_I2_I8)
3293                         sp [-1].data.i = (gint16)sp [-1].data.l;
3294                         ++ip;
3295                         MINT_IN_BREAK;
3296                 MINT_IN_CASE(MINT_CONV_I2_R8)
3297                         sp [-1].data.i = (gint16)sp [-1].data.f;
3298                         ++ip;
3299                         MINT_IN_BREAK;
3300                 MINT_IN_CASE(MINT_CONV_U2_I4)
3301                         sp [-1].data.i = (guint16)sp [-1].data.i;
3302                         ++ip;
3303                         MINT_IN_BREAK;
3304                 MINT_IN_CASE(MINT_CONV_U2_I8)
3305                         sp [-1].data.i = (guint16)sp [-1].data.l;
3306                         ++ip;
3307                         MINT_IN_BREAK;
3308                 MINT_IN_CASE(MINT_CONV_U2_R8)
3309                         sp [-1].data.i = (guint16)sp [-1].data.f;
3310                         ++ip;
3311                         MINT_IN_BREAK;
3312                 MINT_IN_CASE(MINT_CONV_I4_R8)
3313                         sp [-1].data.i = (gint32)sp [-1].data.f;
3314                         ++ip;
3315                         MINT_IN_BREAK;
3316                 MINT_IN_CASE(MINT_CONV_U4_I8)
3317                 MINT_IN_CASE(MINT_CONV_I4_I8)
3318                         sp [-1].data.i = (gint32)sp [-1].data.l;
3319                         ++ip;
3320                         MINT_IN_BREAK;
3321                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
3322                         sp [-2].data.i = (gint32)sp [-2].data.l;
3323                         ++ip;
3324                         MINT_IN_BREAK;
3325                 MINT_IN_CASE(MINT_CONV_U4_R8)
3326                         sp [-1].data.i = (guint32)sp [-1].data.f;
3327                         ++ip;
3328                         MINT_IN_BREAK;
3329                 MINT_IN_CASE(MINT_CONV_I8_I4)
3330                         sp [-1].data.l = sp [-1].data.i;
3331                         ++ip;
3332                         MINT_IN_BREAK;
3333                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
3334                         sp [-2].data.l = sp [-2].data.i;
3335                         ++ip;
3336                         MINT_IN_BREAK;
3337                 MINT_IN_CASE(MINT_CONV_I8_U4)
3338                         sp [-1].data.l = (guint32)sp [-1].data.i;
3339                         ++ip;
3340                         MINT_IN_BREAK;
3341                 MINT_IN_CASE(MINT_CONV_I8_R8)
3342                         sp [-1].data.l = (gint64)sp [-1].data.f;
3343                         ++ip;
3344                         MINT_IN_BREAK;
3345                 MINT_IN_CASE(MINT_CONV_R4_I4)
3346                         sp [-1].data.f = (float)sp [-1].data.i;
3347                         ++ip;
3348                         MINT_IN_BREAK;
3349                 MINT_IN_CASE(MINT_CONV_R4_I8)
3350                         sp [-1].data.f = (float)sp [-1].data.l;
3351                         ++ip;
3352                         MINT_IN_BREAK;
3353                 MINT_IN_CASE(MINT_CONV_R4_R8)
3354                         sp [-1].data.f = (float)sp [-1].data.f;
3355                         ++ip;
3356                         MINT_IN_BREAK;
3357                 MINT_IN_CASE(MINT_CONV_R8_I4)
3358                         sp [-1].data.f = (double)sp [-1].data.i;
3359                         ++ip;
3360                         MINT_IN_BREAK;
3361                 MINT_IN_CASE(MINT_CONV_R8_I8)
3362                         sp [-1].data.f = (double)sp [-1].data.l;
3363                         ++ip;
3364                         MINT_IN_BREAK;
3365                 MINT_IN_CASE(MINT_CONV_U8_I4)
3366                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
3367                         ++ip;
3368                         MINT_IN_BREAK;
3369                 MINT_IN_CASE(MINT_CONV_U8_R8)
3370                         sp [-1].data.l = (guint64)sp [-1].data.f;
3371                         ++ip;
3372                         MINT_IN_BREAK;
3373                 MINT_IN_CASE(MINT_CPOBJ) {
3374                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3375                         g_assert (c->byval_arg.type == MONO_TYPE_VALUETYPE);
3376                         /* if this assertion fails, we need to add a write barrier */
3377                         g_assert (!MONO_TYPE_IS_REFERENCE (&c->byval_arg));
3378                         stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
3379                         ip += 2;
3380                         sp -= 2;
3381                         MINT_IN_BREAK;
3382                 }
3383                 MINT_IN_CASE(MINT_LDOBJ) {
3384                         void *p;
3385                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3386                         ip += 2;
3387                         p = sp [-1].data.p;
3388                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3389                                 int size = mono_class_value_size (c, NULL);
3390                                 sp [-1].data.p = vt_sp;
3391                                 vt_sp += (size + 7) & ~7;
3392                         }
3393                         stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
3394                         MINT_IN_BREAK;
3395                 }
3396                 MINT_IN_CASE(MINT_LDSTR)
3397                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3398                         ++sp;
3399                         ip += 2;
3400                         MINT_IN_BREAK;
3401                 MINT_IN_CASE(MINT_NEWOBJ) {
3402                         MonoClass *newobj_class;
3403                         MonoMethodSignature *csig;
3404                         stackval valuetype_this;
3405                         guint32 token;
3406                         stackval retval;
3407
3408                         frame->ip = ip;
3409
3410                         token = * (guint16 *)(ip + 1);
3411                         ip += 2;
3412
3413                         child_frame.ip = NULL;
3414                         child_frame.ex = NULL;
3415
3416                         child_frame.runtime_method = rtm->data_items [token];
3417                         csig = mono_method_signature (child_frame.runtime_method->method);
3418                         newobj_class = child_frame.runtime_method->method->klass;
3419                         /*if (profiling_classes) {
3420                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
3421                                 count++;
3422                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
3423                         }*/
3424
3425                         if (newobj_class->parent == mono_defaults.array_class) {
3426                                 sp -= csig->param_count;
3427                                 child_frame.stack_args = sp;
3428                                 o = ves_array_create (&child_frame, context->domain, newobj_class, csig, sp);
3429                                 if (child_frame.ex)
3430                                         THROW_EX (child_frame.ex, ip);
3431                                 goto array_constructed;
3432                         }
3433
3434                         g_assert (csig->hasthis);
3435                         if (csig->param_count) {
3436                                 sp -= csig->param_count;
3437                                 memmove (sp + 1, sp, csig->param_count * sizeof (stackval));
3438                         }
3439                         child_frame.stack_args = sp;
3440
3441                         /*
3442                          * First arg is the object.
3443                          */
3444                         if (newobj_class->valuetype) {
3445                                 MonoType *t = &newobj_class->byval_arg;
3446                                 memset (&valuetype_this, 0, sizeof (stackval));
3447                                 if (!newobj_class->enumtype && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
3448                                         sp->data.p = vt_sp;
3449                                         valuetype_this.data.p = vt_sp;
3450                                 } else {
3451                                         sp->data.p = &valuetype_this;
3452                                 }
3453                         } else {
3454                                 if (newobj_class != mono_defaults.string_class) {
3455                                         context->managed_code = 0;
3456                                         o = mono_object_new_checked (context->domain, newobj_class, &error);
3457                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3458                                         context->managed_code = 1;
3459                                         if (*mono_thread_interruption_request_flag ())
3460                                                 mono_thread_interruption_checkpoint ();
3461                                         sp->data.p = o;
3462                                 } else {
3463                                         sp->data.p = NULL;
3464                                         child_frame.retval = &retval;
3465                                 }
3466                         }
3467
3468                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
3469
3470                         ves_exec_method_with_context (&child_frame, context);
3471
3472                         context->current_frame = frame;
3473
3474                         if (child_frame.ex) {
3475                                 /*
3476                                  * An exception occurred, need to run finally, fault and catch handlers..
3477                                  */
3478                                 frame->ex = child_frame.ex;
3479                                 goto handle_finally;
3480                         }
3481                         /*
3482                          * a constructor returns void, but we need to return the object we created
3483                          */
3484 array_constructed:
3485                         if (newobj_class->valuetype && !newobj_class->enumtype) {
3486                                 *sp = valuetype_this;
3487                         } else if (newobj_class == mono_defaults.string_class) {
3488                                 *sp = retval;
3489                         } else {
3490                                 sp->data.p = o;
3491                         }
3492                         ++sp;
3493                         MINT_IN_BREAK;
3494                 }
3495                 MINT_IN_CASE(MINT_CASTCLASS)
3496                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3497                         if ((o = sp [-1].data.p)) {
3498                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3499                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3500                                 if (!isinst_obj)
3501                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
3502                         }
3503                         ip += 2;
3504                         MINT_IN_BREAK;
3505                 MINT_IN_CASE(MINT_ISINST)
3506                         c = rtm->data_items [*(guint16 *)(ip + 1)];
3507                         if ((o = sp [-1].data.p)) {
3508                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3509                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3510                                 if (!isinst_obj)
3511                                         sp [-1].data.p = NULL;
3512                         }
3513                         ip += 2;
3514                         MINT_IN_BREAK;
3515                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
3516                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
3517                         ++ip;
3518                         MINT_IN_BREAK;
3519                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
3520                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
3521                         ++ip;
3522                         MINT_IN_BREAK;
3523                 MINT_IN_CASE(MINT_UNBOX)
3524                         c = rtm->data_items[*(guint16 *)(ip + 1)];
3525                         
3526                         o = sp [-1].data.p;
3527                         if (!o)
3528                                 THROW_EX (mono_get_exception_null_reference (), ip);
3529
3530                         MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
3531                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3532                         if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
3533                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
3534
3535                         sp [-1].data.p = mono_object_unbox (o);
3536                         ip += 2;
3537                         MINT_IN_BREAK;
3538                 MINT_IN_CASE(MINT_THROW)
3539                         --sp;
3540                         frame->ex_handler = NULL;
3541                         if (!sp->data.p)
3542                                 sp->data.p = mono_get_exception_null_reference ();
3543                         THROW_EX ((MonoException *)sp->data.p, ip);
3544                         MINT_IN_BREAK;
3545                 MINT_IN_CASE(MINT_LDFLDA_UNSAFE)
3546                         o = sp [-1].data.p;
3547                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3548                         ip += 2;
3549                         MINT_IN_BREAK;
3550                 MINT_IN_CASE(MINT_LDFLDA)
3551                         o = sp [-1].data.p;
3552                         if (!o)
3553                                 THROW_EX (mono_get_exception_null_reference (), ip);
3554                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
3555                         ip += 2;
3556                         MINT_IN_BREAK;
3557                 MINT_IN_CASE(MINT_CKNULL)
3558                         o = sp [-1].data.p;
3559                         if (!o)
3560                                 THROW_EX (mono_get_exception_null_reference (), ip);
3561                         ++ip;
3562                         MINT_IN_BREAK;
3563
3564 #define LDFLD(datamem, fieldtype) \
3565         o = sp [-1].data.p; \
3566         if (!o) \
3567                 THROW_EX (mono_get_exception_null_reference (), ip); \
3568         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
3569         ip += 2;
3570
3571                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
3572                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
3573                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
3574                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
3575                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
3576                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
3577                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
3578                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
3579                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
3580                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
3581
3582                 MINT_IN_CASE(MINT_LDFLD_VT)
3583                         o = sp [-1].data.p;
3584                         if (!o)
3585                                 THROW_EX (mono_get_exception_null_reference (), ip);
3586                         i32 = READ32(ip + 2);
3587                         sp [-1].data.p = vt_sp;
3588                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3589                         vt_sp += (i32 + 7) & ~7;
3590                         ip += 4;
3591                         MINT_IN_BREAK;
3592
3593                 MINT_IN_CASE(MINT_LDRMFLD) {
3594                         gpointer tmp;
3595                         MonoClassField *field;
3596                         char *addr;
3597
3598                         o = sp [-1].data.p;
3599                         if (!o)
3600                                 THROW_EX (mono_get_exception_null_reference (), ip);
3601                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3602                         ip += 2;
3603                         if (mono_object_is_transparent_proxy (o)) {
3604                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3605
3606                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3607                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3608                         } else {
3609                                 addr = (char*)o + field->offset;
3610                         }                               
3611
3612                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
3613                         MINT_IN_BREAK;
3614                 }
3615
3616                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
3617                         MonoClassField *field;
3618                         char *addr;
3619                         gpointer tmp;
3620
3621                         o = sp [-1].data.p;
3622                         if (!o)
3623                                 THROW_EX (mono_get_exception_null_reference (), ip);
3624                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3625                         i32 = READ32(ip + 2);
3626                         ip += 4;
3627                         if (mono_object_is_transparent_proxy (o)) {
3628                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3629                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3630                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3631                         } else {
3632                                 addr = (char*)o + field->offset;
3633                         }                               
3634
3635                         sp [-1].data.p = vt_sp;
3636                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3637                         vt_sp += (i32 + 7) & ~7;
3638                         memcpy(sp [-1].data.p, addr, i32);
3639                         MINT_IN_BREAK;
3640                 }
3641
3642 #define STFLD(datamem, fieldtype) \
3643         o = sp [-2].data.p; \
3644         if (!o) \
3645                 THROW_EX (mono_get_exception_null_reference (), ip); \
3646         sp -= 2; \
3647         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
3648         ip += 2;
3649
3650                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
3651                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
3652                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
3653                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
3654                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
3655                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
3656                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
3657                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
3658                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
3659                 MINT_IN_CASE(MINT_STFLD_O)
3660                         o = sp [-2].data.p;
3661                         if (!o)
3662                                 THROW_EX (mono_get_exception_null_reference (), ip);
3663                         sp -= 2;
3664                         mono_gc_wbarrier_set_field (o, (char *) o + * (guint16 *)(ip + 1), sp [1].data.p);
3665                         ip += 2;
3666                         MINT_IN_BREAK;
3667
3668                 MINT_IN_CASE(MINT_STFLD_VT)
3669                         o = sp [-2].data.p;
3670                         if (!o)
3671                                 THROW_EX (mono_get_exception_null_reference (), ip);
3672                         i32 = READ32(ip + 2);
3673                         sp -= 2;
3674                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
3675                         vt_sp -= (i32 + 7) & ~7;
3676                         ip += 4;
3677                         MINT_IN_BREAK;
3678
3679                 MINT_IN_CASE(MINT_STRMFLD) {
3680                         MonoClassField *field;
3681
3682                         o = sp [-2].data.p;
3683                         if (!o)
3684                                 THROW_EX (mono_get_exception_null_reference (), ip);
3685                         
3686                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3687                         ip += 2;
3688
3689                         if (mono_object_is_transparent_proxy (o)) {
3690                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3691                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3692                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3693                         } else
3694                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
3695
3696                         sp -= 2;
3697                         MINT_IN_BREAK;
3698                 }
3699                 MINT_IN_CASE(MINT_STRMFLD_VT) {
3700                         MonoClassField *field;
3701
3702                         o = sp [-2].data.p;
3703                         if (!o)
3704                                 THROW_EX (mono_get_exception_null_reference (), ip);
3705                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3706                         i32 = READ32(ip + 2);
3707                         ip += 4;
3708
3709                         if (mono_object_is_transparent_proxy (o)) {
3710                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3711                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3712                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3713                         } else
3714                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
3715
3716                         sp -= 2;
3717                         vt_sp -= (i32 + 7) & ~7;
3718                         MINT_IN_BREAK;
3719                 }
3720                 MINT_IN_CASE(MINT_LDSFLDA) {
3721                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
3722                         sp->data.p = mono_class_static_field_address (context->domain, field);
3723                         ip += 2;
3724                         ++sp;
3725                         MINT_IN_BREAK;
3726                 }
3727                 MINT_IN_CASE(MINT_LDSFLD) {
3728                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3729                         gpointer addr = mono_class_static_field_address (context->domain, field);
3730                         stackval_from_data (field->type, sp, addr, FALSE);
3731                         ip += 2;
3732                         ++sp;
3733                         MINT_IN_BREAK;
3734                 }
3735                 MINT_IN_CASE(MINT_LDSFLD_VT) {
3736                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3737                         gpointer addr = mono_class_static_field_address (context->domain, field);
3738                         int size = READ32 (ip + 2);
3739                         ip += 4;
3740
3741                         sp->data.p = vt_sp;
3742                         vt_sp += (size + 7) & ~7;
3743                         stackval_from_data (field->type, sp, addr, FALSE);
3744                         ++sp;
3745                         MINT_IN_BREAK;
3746                 }
3747                 MINT_IN_CASE(MINT_STSFLD) {
3748                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3749                         gpointer addr = mono_class_static_field_address (context->domain, field);
3750                         ip += 2;
3751                         --sp;
3752                         stackval_to_data (field->type, sp, addr, FALSE);
3753                         MINT_IN_BREAK;
3754                 }
3755                 MINT_IN_CASE(MINT_STSFLD_VT) {
3756                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3757                         gpointer addr = mono_class_static_field_address (context->domain, field);
3758                         int size = READ32 (ip + 2);
3759                         ip += 4;
3760
3761                         --sp;
3762                         stackval_to_data (field->type, sp, addr, FALSE);
3763                         vt_sp -= (size + 7) & ~7;
3764                         MINT_IN_BREAK;
3765                 }
3766                 MINT_IN_CASE(MINT_STOBJ_VT) {
3767                         int size;
3768                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3769                         ip += 2;
3770                         size = mono_class_value_size (c, NULL);
3771                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
3772                         vt_sp -= (size + 7) & ~7;
3773                         sp -= 2;
3774                         MINT_IN_BREAK;
3775                 }
3776                 MINT_IN_CASE(MINT_STOBJ) {
3777                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3778                         ip += 2;
3779
3780                         g_assert (!c->byval_arg.byref);
3781                         if (MONO_TYPE_IS_REFERENCE (&c->byval_arg))
3782                                 mono_gc_wbarrier_generic_store (sp [-2].data.p, sp [-1].data.p);
3783                         else
3784                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, (char *) &sp [-1].data.p, FALSE);
3785                         sp -= 2;
3786                         MINT_IN_BREAK;
3787                 }
3788                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
3789                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3790                                 THROW_EX (mono_get_exception_overflow (), ip);
3791                         sp [-1].data.i = (guint32)sp [-1].data.f;
3792                         ++ip;
3793                         MINT_IN_BREAK;
3794                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
3795                         if (sp [-1].data.i < 0)
3796                                 THROW_EX (mono_get_exception_overflow (), ip);
3797                         sp [-1].data.l = sp [-1].data.i;
3798                         ++ip;
3799                         MINT_IN_BREAK;
3800                 MINT_IN_CASE(MINT_CONV_OVF_U8_I8)
3801                         if (sp [-1].data.l < 0)
3802                                 THROW_EX (mono_get_exception_overflow (), ip);
3803                         ++ip;
3804                         MINT_IN_BREAK;
3805                 MINT_IN_CASE(MINT_CONV_OVF_I8_U8)
3806                         if ((guint64) sp [-1].data.l > MYGINT64_MAX)
3807                                 THROW_EX (mono_get_exception_overflow (), ip);
3808                         ++ip;
3809                         MINT_IN_BREAK;
3810                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
3811                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
3812                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGINT64_MAX)
3813                                 THROW_EX (mono_get_exception_overflow (), ip);
3814                         sp [-1].data.l = (guint64)sp [-1].data.f;
3815                         ++ip;
3816                         MINT_IN_BREAK;
3817                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
3818                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
3819                                 THROW_EX (mono_get_exception_overflow (), ip);
3820                         sp [-1].data.l = (gint64)sp [-1].data.f;
3821                         ++ip;
3822                         MINT_IN_BREAK;
3823                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
3824                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
3825                                 THROW_EX (mono_get_exception_overflow (), ip);
3826                         sp [-1].data.i = (mono_u)sp [-1].data.l;
3827                         ++ip;
3828                         MINT_IN_BREAK;
3829                 MINT_IN_CASE(MINT_BOX) {
3830                         c = rtm->data_items [* (guint16 *)(ip + 1)];
3831                         guint16 offset = * (guint16 *)(ip + 2);
3832
3833                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3834                                 int size = mono_class_value_size (c, NULL);
3835                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
3836                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3837                                 size = (size + 7) & ~7;
3838                                 vt_sp -= size;
3839                         } else {
3840                                 stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
3841                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
3842                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3843                         }
3844                         ip += 3;
3845                         MINT_IN_BREAK;
3846                 }
3847                 MINT_IN_CASE(MINT_NEWARR)
3848                         sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
3849                         if (!mono_error_ok (&error)) {
3850                                 THROW_EX (mono_error_convert_to_exception (&error), ip);
3851                         }
3852                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3853                         ip += 2;
3854                         /*if (profiling_classes) {
3855                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3856                                 count++;
3857                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3858                         }*/
3859
3860                         MINT_IN_BREAK;
3861                 MINT_IN_CASE(MINT_LDLEN)
3862                         o = sp [-1].data.p;
3863                         if (!o)
3864                                 THROW_EX (mono_get_exception_null_reference (), ip);
3865                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3866                         ++ip;
3867                         MINT_IN_BREAK;
3868                 MINT_IN_CASE(MINT_GETCHR) {
3869                         MonoString *s;
3870                         s = sp [-2].data.p;
3871                         if (!s)
3872                                 THROW_EX (mono_get_exception_null_reference (), ip);
3873                         i32 = sp [-1].data.i;
3874                         if (i32 < 0 || i32 >= mono_string_length (s))
3875                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3876                         --sp;
3877                         sp [-1].data.i = mono_string_chars(s)[i32];
3878                         ++ip;
3879                         MINT_IN_BREAK;
3880                 }
3881                 MINT_IN_CASE(MINT_STRLEN)
3882                         ++ip;
3883                         o = sp [-1].data.p;
3884                         if (!o)
3885                                 THROW_EX (mono_get_exception_null_reference (), ip);
3886                         sp [-1].data.i = mono_string_length ((MonoString*) o);
3887                         MINT_IN_BREAK;
3888                 MINT_IN_CASE(MINT_ARRAY_RANK)
3889                         o = sp [-1].data.p;
3890                         if (!o)
3891                                 THROW_EX (mono_get_exception_null_reference (), ip);
3892                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
3893                         ip++;
3894                         MINT_IN_BREAK;
3895                 MINT_IN_CASE(MINT_LDELEMA)
3896                 MINT_IN_CASE(MINT_LDELEMA_TC) {
3897                         gboolean needs_typecheck = *ip == MINT_LDELEMA_TC;
3898                         
3899                         MonoClass *klass = rtm->data_items [*(guint16 *) (ip + 1)];
3900                         guint16 numargs = *(guint16 *) (ip + 2);
3901                         ip += 3;
3902                         sp -= numargs;
3903
3904                         o = sp [0].data.p;
3905                         sp->data.p = ves_array_element_address (frame, klass, (MonoArray *) o, &sp [1], needs_typecheck);
3906                         if (frame->ex)
3907                                 THROW_EX (frame->ex, ip);
3908                         ++sp;
3909
3910                         MINT_IN_BREAK;
3911                 }
3912                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
3913                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
3914                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
3915                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
3916                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
3917                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
3918                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
3919                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
3920                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
3921                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
3922                 MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
3923                 MINT_IN_CASE(MINT_LDELEM_VT) {
3924                         MonoArray *o;
3925                         mono_u aindex;
3926
3927                         sp -= 2;
3928
3929                         o = sp [0].data.p;
3930                         if (!o)
3931                                 THROW_EX (mono_get_exception_null_reference (), ip);
3932
3933                         aindex = sp [1].data.i;
3934                         if (aindex >= mono_array_length (o))
3935                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3936
3937                         /*
3938                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3939                          */
3940                         switch (*ip) {
3941                         case MINT_LDELEM_I1:
3942                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
3943                                 break;
3944                         case MINT_LDELEM_U1:
3945                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
3946                                 break;
3947                         case MINT_LDELEM_I2:
3948                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
3949                                 break;
3950                         case MINT_LDELEM_U2:
3951                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
3952                                 break;
3953                         case MINT_LDELEM_I:
3954                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
3955                                 break;
3956                         case MINT_LDELEM_I4:
3957                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
3958                                 break;
3959                         case MINT_LDELEM_U4:
3960                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
3961                                 break;
3962                         case MINT_LDELEM_I8:
3963                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
3964                                 break;
3965                         case MINT_LDELEM_R4:
3966                                 sp [0].data.f = mono_array_get (o, float, aindex);
3967                                 break;
3968                         case MINT_LDELEM_R8:
3969                                 sp [0].data.f = mono_array_get (o, double, aindex);
3970                                 break;
3971                         case MINT_LDELEM_REF:
3972                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
3973                                 break;
3974                         case MINT_LDELEM_VT: {
3975                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
3976                                 i32 = READ32 (ip + 2);
3977                                 char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
3978                                 sp [0].data.vt = vt_sp;
3979                                 stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
3980                                 vt_sp += (i32 + 7) & ~7;
3981                                 ip += 3;
3982                                 break;
3983                         }
3984                         default:
3985                                 ves_abort();
3986                         }
3987
3988                         ++ip;
3989                         ++sp;
3990                         MINT_IN_BREAK;
3991                 }
3992                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
3993                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
3994                 MINT_IN_CASE(MINT_STELEM_U1) /* fall through */
3995                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
3996                 MINT_IN_CASE(MINT_STELEM_U2) /* fall through */
3997                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
3998                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
3999                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
4000                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
4001                 MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
4002                 MINT_IN_CASE(MINT_STELEM_VT) {
4003                         mono_u aindex;
4004
4005                         sp -= 3;
4006
4007                         o = sp [0].data.p;
4008                         if (!o)
4009                                 THROW_EX (mono_get_exception_null_reference (), ip);
4010
4011                         aindex = sp [1].data.i;
4012                         if (aindex >= mono_array_length ((MonoArray *)o))
4013                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
4014
4015                         switch (*ip) {
4016                         case MINT_STELEM_I:
4017                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
4018                                 break;
4019                         case MINT_STELEM_I1:
4020                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
4021                                 break;
4022                         case MINT_STELEM_U1:
4023                                 mono_array_set ((MonoArray *) o, guint8, aindex, sp [2].data.i);
4024                                 break;
4025                         case MINT_STELEM_I2:
4026                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
4027                                 break;
4028                         case MINT_STELEM_U2:
4029                                 mono_array_set ((MonoArray *)o, guint16, aindex, sp [2].data.i);
4030                                 break;
4031                         case MINT_STELEM_I4:
4032                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
4033                                 break;
4034                         case MINT_STELEM_I8:
4035                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
4036                                 break;
4037                         case MINT_STELEM_R4:
4038                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
4039                                 break;
4040                         case MINT_STELEM_R8:
4041                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
4042                                 break;
4043                         case MINT_STELEM_REF: {
4044                                 MonoObject *isinst_obj = mono_object_isinst_checked (sp [2].data.p, mono_object_class (o)->element_class, &error);
4045                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4046                                 if (sp [2].data.p && !isinst_obj)
4047                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
4048                                 mono_array_setref ((MonoArray *) o, aindex, sp [2].data.p);
4049                                 break;
4050                         }
4051                         case MINT_STELEM_VT: {
4052                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
4053                                 i32 = READ32 (ip + 2);
4054                                 char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
4055
4056                                 stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
4057                                 vt_sp -= (i32 + 7) & ~7;
4058                                 ip += 3;
4059                                 break;
4060                         }
4061                         default:
4062                                 ves_abort();
4063                         }
4064
4065                         ++ip;
4066                         MINT_IN_BREAK;
4067                 }
4068                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
4069                         if (sp [-1].data.i < 0)
4070                                 THROW_EX (mono_get_exception_overflow (), ip);
4071                         ++ip;
4072                         MINT_IN_BREAK;
4073                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
4074                         if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
4075                                 THROW_EX (mono_get_exception_overflow (), ip);
4076                         sp [-1].data.i = (gint32) sp [-1].data.l;
4077                         ++ip;
4078                         MINT_IN_BREAK;
4079                 MINT_IN_CASE(MINT_CONV_OVF_I4_U8)
4080                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGINT32_MAX)
4081                                 THROW_EX (mono_get_exception_overflow (), ip);
4082                         sp [-1].data.i = (gint32) sp [-1].data.l;
4083                         ++ip;
4084                         MINT_IN_BREAK;
4085                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
4086                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
4087                                 THROW_EX (mono_get_exception_overflow (), ip);
4088                         sp [-1].data.i = (gint32) sp [-1].data.f;
4089                         ++ip;
4090                         MINT_IN_BREAK;
4091                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
4092                         if (sp [-1].data.i < 0)
4093                                 THROW_EX (mono_get_exception_overflow (), ip);
4094                         ++ip;
4095                         MINT_IN_BREAK;
4096                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
4097                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
4098                                 THROW_EX (mono_get_exception_overflow (), ip);
4099                         sp [-1].data.i = (guint32) sp [-1].data.l;
4100                         ++ip;
4101                         MINT_IN_BREAK;
4102                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
4103                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
4104                                 THROW_EX (mono_get_exception_overflow (), ip);
4105                         sp [-1].data.i = (guint32) sp [-1].data.f;
4106                         ++ip;
4107                         MINT_IN_BREAK;
4108                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
4109                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
4110                                 THROW_EX (mono_get_exception_overflow (), ip);
4111                         ++ip;
4112                         MINT_IN_BREAK;
4113                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
4114                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
4115                                 THROW_EX (mono_get_exception_overflow (), ip);
4116                         sp [-1].data.i = (gint16) sp [-1].data.l;
4117                         ++ip;
4118                         MINT_IN_BREAK;
4119                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
4120                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
4121                                 THROW_EX (mono_get_exception_overflow (), ip);
4122                         sp [-1].data.i = (gint16) sp [-1].data.f;
4123                         ++ip;
4124                         MINT_IN_BREAK;
4125                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
4126                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
4127                                 THROW_EX (mono_get_exception_overflow (), ip);
4128                         ++ip;
4129                         MINT_IN_BREAK;
4130                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
4131                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
4132                                 THROW_EX (mono_get_exception_overflow (), ip);
4133                         sp [-1].data.i = (guint16) sp [-1].data.l;
4134                         ++ip;
4135                         MINT_IN_BREAK;
4136                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
4137                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
4138                                 THROW_EX (mono_get_exception_overflow (), ip);
4139                         sp [-1].data.i = (guint16) sp [-1].data.f;
4140                         ++ip;
4141                         MINT_IN_BREAK;
4142                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
4143                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
4144                                 THROW_EX (mono_get_exception_overflow (), ip);
4145                         ++ip;
4146                         MINT_IN_BREAK;
4147                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
4148                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
4149                                 THROW_EX (mono_get_exception_overflow (), ip);
4150                         sp [-1].data.i = (gint8) sp [-1].data.l;
4151                         ++ip;
4152                         MINT_IN_BREAK;
4153                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
4154                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
4155                                 THROW_EX (mono_get_exception_overflow (), ip);
4156                         sp [-1].data.i = (gint8) sp [-1].data.f;
4157                         ++ip;
4158                         MINT_IN_BREAK;
4159                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
4160                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
4161                                 THROW_EX (mono_get_exception_overflow (), ip);
4162                         ++ip;
4163                         MINT_IN_BREAK;
4164                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
4165                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
4166                                 THROW_EX (mono_get_exception_overflow (), ip);
4167                         sp [-1].data.i = (guint8) sp [-1].data.l;
4168                         ++ip;
4169                         MINT_IN_BREAK;
4170                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
4171                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
4172                                 THROW_EX (mono_get_exception_overflow (), ip);
4173                         sp [-1].data.i = (guint8) sp [-1].data.f;
4174                         ++ip;
4175                         MINT_IN_BREAK;
4176 #if 0
4177                 MINT_IN_CASE(MINT_LDELEM) 
4178                 MINT_IN_CASE(MINT_STELEM) 
4179                 MINT_IN_CASE(MINT_UNBOX_ANY) 
4180
4181                 MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
4182 #endif
4183                 MINT_IN_CASE(MINT_CKFINITE)
4184                         if (!isfinite(sp [-1].data.f))
4185                                 THROW_EX (mono_get_exception_arithmetic (), ip);
4186                         ++ip;
4187                         MINT_IN_BREAK;
4188 #if 0
4189                 MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
4190 #endif
4191                 MINT_IN_CASE(MINT_LDTOKEN)
4192                         sp->data.p = vt_sp;
4193                         vt_sp += 8;
4194                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
4195                         ip += 2;
4196                         ++sp;
4197                         MINT_IN_BREAK;
4198                 MINT_IN_CASE(MINT_ADD_OVF_I4)
4199                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4200                                 THROW_EX (mono_get_exception_overflow (), ip);
4201                         BINOP(i, +);
4202                         MINT_IN_BREAK;
4203                 MINT_IN_CASE(MINT_ADD_OVF_I8)
4204                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4205                                 THROW_EX (mono_get_exception_overflow (), ip);
4206                         BINOP(l, +);
4207                         MINT_IN_BREAK;
4208                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
4209                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4210                                 THROW_EX (mono_get_exception_overflow (), ip);
4211                         BINOP_CAST(i, +, guint32);
4212                         MINT_IN_BREAK;
4213                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
4214                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4215                                 THROW_EX (mono_get_exception_overflow (), ip);
4216                         BINOP_CAST(l, +, guint64);
4217                         MINT_IN_BREAK;
4218                 MINT_IN_CASE(MINT_MUL_OVF_I4)
4219                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4220                                 THROW_EX (mono_get_exception_overflow (), ip);
4221                         BINOP(i, *);
4222                         MINT_IN_BREAK;
4223                 MINT_IN_CASE(MINT_MUL_OVF_I8)
4224                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4225                                 THROW_EX (mono_get_exception_overflow (), ip);
4226                         BINOP(l, *);
4227                         MINT_IN_BREAK;
4228                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
4229                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4230                                 THROW_EX (mono_get_exception_overflow (), ip);
4231                         BINOP_CAST(i, *, guint32);
4232                         MINT_IN_BREAK;
4233                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
4234                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4235                                 THROW_EX (mono_get_exception_overflow (), ip);
4236                         BINOP_CAST(l, *, guint64);
4237                         MINT_IN_BREAK;
4238                 MINT_IN_CASE(MINT_SUB_OVF_I4)
4239                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
4240                                 THROW_EX (mono_get_exception_overflow (), ip);
4241                         BINOP(i, -);
4242                         MINT_IN_BREAK;
4243                 MINT_IN_CASE(MINT_SUB_OVF_I8)
4244                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
4245                                 THROW_EX (mono_get_exception_overflow (), ip);
4246                         BINOP(l, -);
4247                         MINT_IN_BREAK;
4248                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
4249                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
4250                                 THROW_EX (mono_get_exception_overflow (), ip);
4251                         BINOP_CAST(i, -, guint32);
4252                         MINT_IN_BREAK;
4253                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
4254                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
4255                                 THROW_EX (mono_get_exception_overflow (), ip);
4256                         BINOP_CAST(l, -, guint64);
4257                         MINT_IN_BREAK;
4258                 MINT_IN_CASE(MINT_ENDFINALLY)
4259                         while (sp > frame->stack) {
4260                                 --sp;
4261                         }
4262                         if (finally_ips) {
4263                                 ip = finally_ips->data;
4264                                 finally_ips = g_slist_remove (finally_ips, ip);
4265                                 goto main_loop;
4266                         }
4267                         if (frame->ex)
4268                                 goto handle_fault;
4269                         ves_abort();
4270                         MINT_IN_BREAK;
4271                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
4272                 MINT_IN_CASE(MINT_LEAVE_S)
4273                         while (sp > frame->stack) {
4274                                 --sp;
4275                         }
4276                         frame->ip = ip;
4277                         if (*ip == MINT_LEAVE_S) {
4278                                 ip += (short) *(ip + 1);
4279                         } else {
4280                                 ip += (gint32) READ32 (ip + 1);
4281                         }
4282                         endfinally_ip = ip;
4283                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
4284                                 frame->ex_handler = NULL;
4285                                 frame->ex = NULL;
4286                         }
4287                         goto handle_finally;
4288                         MINT_IN_BREAK;
4289                 MINT_IN_CASE(MINT_ICALL_V_V) 
4290                 MINT_IN_CASE(MINT_ICALL_V_P)
4291                 MINT_IN_CASE(MINT_ICALL_P_V) 
4292                 MINT_IN_CASE(MINT_ICALL_P_P)
4293                 MINT_IN_CASE(MINT_ICALL_PP_V)
4294                 MINT_IN_CASE(MINT_ICALL_PI_V)
4295                 MINT_IN_CASE(MINT_ICALL_PP_P)
4296                 MINT_IN_CASE(MINT_ICALL_PI_P)
4297                 MINT_IN_CASE(MINT_ICALL_PPP_V)
4298                 MINT_IN_CASE(MINT_ICALL_PPI_V)
4299                         sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
4300                         if (frame->ex != NULL)
4301                                 goto handle_exception;
4302                         ip += 2;
4303                         MINT_IN_BREAK;
4304                 MINT_IN_CASE(MINT_MONO_LDPTR) 
4305                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
4306                         ip += 2;
4307                         ++sp;
4308                         MINT_IN_BREAK;
4309                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
4310                         sp->data.p = mono_object_new_checked (context->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
4311                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4312                         ip += 2;
4313                         sp++;
4314                         MINT_IN_BREAK;
4315                 MINT_IN_CASE(MINT_MONO_FREE)
4316                         ++ip;
4317                         --sp;
4318                         g_error ("that doesn't seem right");
4319                         g_free (sp->data.p);
4320                         MINT_IN_BREAK;
4321                 MINT_IN_CASE(MINT_MONO_RETOBJ)
4322                         ++ip;
4323                         sp--;
4324                         stackval_from_data (mono_method_signature (frame->runtime_method->method)->ret, frame->retval, sp->data.p,
4325                              mono_method_signature (frame->runtime_method->method)->pinvoke);
4326                         if (sp > frame->stack)
4327                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
4328                         goto exit_frame;
4329
4330 #define RELOP(datamem, op) \
4331         --sp; \
4332         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
4333         ++ip;
4334                 MINT_IN_CASE(MINT_CEQ_I4)
4335                         RELOP(i, ==);
4336                         MINT_IN_BREAK;
4337                 MINT_IN_CASE(MINT_CEQ0_I4)
4338                         sp [-1].data.i = (sp [-1].data.i == 0);
4339                         ++ip;
4340                         MINT_IN_BREAK;
4341                 MINT_IN_CASE(MINT_CEQ_I8)
4342                         RELOP(l, ==);
4343                         MINT_IN_BREAK;
4344                 MINT_IN_CASE(MINT_CEQ_R8)
4345                         --sp; 
4346                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4347                                 sp [-1].data.i = 0;
4348                         else
4349                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
4350                         ++ip;
4351                         MINT_IN_BREAK;
4352                 MINT_IN_CASE(MINT_CGT_I4)
4353                         RELOP(i, >);
4354                         MINT_IN_BREAK;
4355                 MINT_IN_CASE(MINT_CGT_I8)
4356                         RELOP(l, >);
4357                         MINT_IN_BREAK;
4358                 MINT_IN_CASE(MINT_CGT_R8)
4359                         --sp; 
4360                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4361                                 sp [-1].data.i = 0;
4362                         else
4363                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4364                         ++ip;
4365                         MINT_IN_BREAK;
4366
4367 #define RELOP_CAST(datamem, op, type) \
4368         --sp; \
4369         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
4370         ++ip;
4371
4372                 MINT_IN_CASE(MINT_CGT_UN_I4)
4373                         RELOP_CAST(i, >, guint32);
4374                         MINT_IN_BREAK;
4375                 MINT_IN_CASE(MINT_CGT_UN_I8)
4376                         RELOP_CAST(l, >, guint64);
4377                         MINT_IN_BREAK;
4378                 MINT_IN_CASE(MINT_CGT_UN_R8)
4379                         --sp; 
4380                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4381                                 sp [-1].data.i = 1;
4382                         else
4383                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
4384                         ++ip;
4385                         MINT_IN_BREAK;
4386                 MINT_IN_CASE(MINT_CLT_I4)
4387                         RELOP(i, <);
4388                         MINT_IN_BREAK;
4389                 MINT_IN_CASE(MINT_CLT_I8)
4390                         RELOP(l, <);
4391                         MINT_IN_BREAK;
4392                 MINT_IN_CASE(MINT_CLT_R8)
4393                         --sp; 
4394                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4395                                 sp [-1].data.i = 0;
4396                         else
4397                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4398                         ++ip;
4399                         MINT_IN_BREAK;
4400                 MINT_IN_CASE(MINT_CLT_UN_I4)
4401                         RELOP_CAST(i, <, guint32);
4402                         MINT_IN_BREAK;
4403                 MINT_IN_CASE(MINT_CLT_UN_I8)
4404                         RELOP_CAST(l, <, guint64);
4405                         MINT_IN_BREAK;
4406                 MINT_IN_CASE(MINT_CLT_UN_R8)
4407                         --sp; 
4408                         if (isunordered (sp [-1].data.f, sp [0].data.f))
4409                                 sp [-1].data.i = 1;
4410                         else
4411                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
4412                         ++ip;
4413                         MINT_IN_BREAK;
4414                 MINT_IN_CASE(MINT_LDFTN) {
4415                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
4416                         ++sp;
4417                         ip += 2;
4418                         MINT_IN_BREAK;
4419                 }
4420                 MINT_IN_CASE(MINT_LDVIRTFTN) {
4421                         RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
4422                         ip += 2;
4423                         --sp;
4424                         if (!sp->data.p)
4425                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
4426                                 
4427                         sp->data.p = get_virtual_method (context->domain, m, sp->data.p);
4428                         ++sp;
4429                         MINT_IN_BREAK;
4430                 }
4431
4432 #define LDARG(datamem, argtype) \
4433         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
4434         ip += 2; \
4435         ++sp; 
4436         
4437                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
4438                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
4439                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
4440                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
4441                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
4442                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
4443                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
4444                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
4445                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
4446                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
4447
4448                 MINT_IN_CASE(MINT_LDARG_VT)
4449                         sp->data.p = vt_sp;
4450                         i32 = READ32(ip + 2);
4451                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
4452                         vt_sp += (i32 + 7) & ~7;
4453                         ip += 4;
4454                         ++sp;
4455                         MINT_IN_BREAK;
4456
4457 #define STARG(datamem, argtype) \
4458         --sp; \
4459         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4460         ip += 2; \
4461         
4462                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
4463                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
4464                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
4465                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
4466                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
4467                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
4468                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
4469                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
4470                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
4471                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
4472
4473                 MINT_IN_CASE(MINT_STARG_VT) 
4474                         i32 = READ32(ip + 2);
4475                         --sp;
4476                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
4477                         vt_sp -= (i32 + 7) & ~7;
4478                         ip += 4;
4479                         MINT_IN_BREAK;
4480
4481 #define STINARG(datamem, argtype) \
4482         do { \
4483                 int n = * (guint16 *)(ip + 1); \
4484                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
4485                 ip += 2; \
4486         } while (0)
4487         
4488                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
4489                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
4490                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
4491                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
4492                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
4493                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
4494                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
4495                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
4496                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
4497                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
4498
4499                 MINT_IN_CASE(MINT_STINARG_VT) {
4500                         int n = * (guint16 *)(ip + 1);
4501                         i32 = READ32(ip + 2);
4502                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
4503                         ip += 4;
4504                         MINT_IN_BREAK;
4505                 }
4506
4507                 MINT_IN_CASE(MINT_LDARGA)
4508                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
4509                         ip += 2;
4510                         ++sp;
4511                         MINT_IN_BREAK;
4512
4513 #define LDLOC(datamem, argtype) \
4514         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
4515         ip += 2; \
4516         ++sp; 
4517         
4518                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
4519                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
4520                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
4521                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
4522                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
4523                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
4524                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
4525                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
4526                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
4527                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
4528
4529                 MINT_IN_CASE(MINT_LDLOC_VT)
4530                         sp->data.p = vt_sp;
4531                         i32 = READ32(ip + 2);
4532                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
4533                         vt_sp += (i32 + 7) & ~7;
4534                         ip += 4;
4535                         ++sp;
4536                         MINT_IN_BREAK;
4537
4538                 MINT_IN_CASE(MINT_LDLOCA_S)
4539                         sp->data.p = locals + * (guint16 *)(ip + 1);
4540                         ip += 2;
4541                         ++sp;
4542                         MINT_IN_BREAK;
4543
4544 #define STLOC(datamem, argtype) \
4545         --sp; \
4546         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
4547         ip += 2;
4548         
4549                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
4550                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
4551                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
4552                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
4553                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
4554                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
4555                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
4556                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
4557                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
4558                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
4559
4560 #define STLOC_NP(datamem, argtype) \
4561         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
4562         ip += 2;
4563
4564                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
4565                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
4566
4567                 MINT_IN_CASE(MINT_STLOC_VT)
4568                         i32 = READ32(ip + 2);
4569                         --sp;
4570                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
4571                         vt_sp -= (i32 + 7) & ~7;
4572                         ip += 4;
4573                         MINT_IN_BREAK;
4574
4575                 MINT_IN_CASE(MINT_LOCALLOC) {
4576                         if (sp != frame->stack + 1) /*FIX?*/
4577                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
4578
4579                         int len = sp [-1].data.i;
4580                         sp [-1].data.p = alloca (len);
4581                         MonoMethodHeader *header = mono_method_get_header_checked (frame->runtime_method->method, &error);
4582                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4583                         if (header->init_locals)
4584                                 memset (sp [-1].data.p, 0, len);
4585                         ++ip;
4586                         MINT_IN_BREAK;
4587                 }
4588                 MINT_IN_CASE(MINT_ENDFILTER)
4589                         /* top of stack is result of filter */
4590                         frame->retval = &sp [-1];
4591                         goto exit_frame;
4592                 MINT_IN_CASE(MINT_INITOBJ)
4593                         --sp;
4594                         memset (sp->data.vt, 0, READ32(ip + 1));
4595                         ip += 3;
4596                         MINT_IN_BREAK;
4597                 MINT_IN_CASE(MINT_CPBLK)
4598                         sp -= 3;
4599                         if (!sp [0].data.p || !sp [1].data.p)
4600                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4601                         ++ip;
4602                         /* FIXME: value and size may be int64... */
4603                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4604                         MINT_IN_BREAK;
4605 #if 0
4606                 MINT_IN_CASE(MINT_CONSTRAINED_) {
4607                         guint32 token;
4608                         /* FIXME: implement */
4609                         ++ip;
4610                         token = READ32 (ip);
4611                         ip += 2;
4612                         MINT_IN_BREAK;
4613                 }
4614 #endif
4615                 MINT_IN_CASE(MINT_INITBLK)
4616                         sp -= 3;
4617                         if (!sp [0].data.p)
4618                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4619                         ++ip;
4620                         /* FIXME: value and size may be int64... */
4621                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
4622                         MINT_IN_BREAK;
4623 #if 0
4624                 MINT_IN_CASE(MINT_NO_)
4625                         /* FIXME: implement */
4626                         ip += 2;
4627                         MINT_IN_BREAK;
4628 #endif
4629                 MINT_IN_CASE(MINT_RETHROW)
4630                         /* 
4631                          * need to clarify what this should actually do:
4632                          * start the search from the last found handler in
4633                          * this method or continue in the caller or what.
4634                          * Also, do we need to run finally/fault handlers after a retrow?
4635                          * Well, this implementation will follow the usual search
4636                          * for an handler, considering the current ip as throw spot.
4637                          * We need to NULL frame->ex_handler for the later code to
4638                          * actually run the new found handler.
4639                          */
4640                         frame->ex_handler = NULL;
4641                         THROW_EX (frame->ex, ip - 1);
4642                         MINT_IN_BREAK;
4643                 MINT_IN_DEFAULT
4644                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
4645                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
4646                 }
4647         }
4648
4649         g_assert_not_reached ();
4650         /*
4651          * Exception handling code.
4652          * The exception object is stored in frame->ex.
4653          */
4654
4655         handle_exception:
4656         {
4657                 int i;
4658                 guint32 ip_offset;
4659                 MonoInvocation *inv;
4660                 MonoExceptionClause *clause;
4661                 /*char *message;*/
4662                 MonoObject *ex_obj;
4663
4664 #if DEBUG_INTERP
4665                 if (tracing)
4666                         g_print ("* Handling exception '%s' at IL_%04x\n", 
4667                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
4668                                 rtm == NULL ? 0 : frame->ip - rtm->code);
4669 #endif
4670                 if (die_on_exception)
4671                         goto die_on_ex;
4672
4673                 for (inv = frame; inv; inv = inv->parent) {
4674                         MonoMethod *method;
4675                         if (inv->runtime_method == NULL)
4676                                 continue;
4677                         method = inv->runtime_method->method;
4678                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
4679                                 continue;
4680                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
4681                                 continue;
4682                         if (inv->ip == NULL)
4683                                 continue;
4684                         ip_offset = inv->ip - inv->runtime_method->code;
4685                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
4686                         for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
4687                                 clause = &inv->runtime_method->clauses [i];
4688 #if DEBUG_INTERP
4689                                 g_print ("* clause [%d]: %p\n", i, clause);
4690 #endif
4691                                 if (!MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4692                                         continue;
4693                                 }
4694                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4695 #if DEBUG_INTERP
4696                                         if (tracing)
4697                                                 g_print ("* Filter found at '%s'\n", method->name);
4698 #endif
4699                                         MonoInvocation dup_frame;
4700                                         stackval retval;
4701                                         memcpy (&dup_frame, inv, sizeof (MonoInvocation));
4702                                         dup_frame.retval = &retval;
4703                                         ves_exec_method_with_context_with_ip (&dup_frame, context, inv->runtime_method->code + clause->data.filter_offset, frame->ex);
4704                                         if (dup_frame.retval->data.i) {
4705 #if DEBUG_INTERP
4706                                                 if (tracing)
4707                                                         g_print ("* Matched Filter at '%s'\n", method->name);
4708 #endif
4709                                                 inv->ex_handler = clause;
4710                                                 goto handle_finally;
4711                                         }
4712                                 } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
4713                                         MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
4714                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4715                                         if (isinst_obj) {
4716                                                 /* 
4717                                                  * OK, we found an handler, now we need to execute the finally
4718                                                  * and fault blocks before branching to the handler code.
4719                                                  */
4720 #if DEBUG_INTERP
4721                                                 if (tracing)
4722                                                         g_print ("* Found handler at '%s'\n", method->name);
4723 #endif
4724                                                 inv->ex_handler = clause;
4725                                                 goto handle_finally;
4726                                         }
4727                                 }
4728                         }
4729                 }
4730                 /*
4731                  * If we get here, no handler was found: print a stack trace.
4732                  */
4733                 for (inv = frame; inv; inv = inv->parent) {
4734                         if (inv->invoke_trap)
4735                                 goto handle_finally;
4736                 }
4737 die_on_ex:
4738                 ex_obj = (MonoObject *) frame->ex;
4739                 mono_unhandled_exception (ex_obj);
4740                 MonoJitTlsData *jit_tls = (MonoJitTlsData *) mono_tls_get_jit_tls ();
4741                 jit_tls->abort_func (ex_obj);
4742                 g_assert_not_reached ();
4743         }
4744         handle_finally:
4745         {
4746                 int i;
4747                 guint32 ip_offset;
4748                 MonoExceptionClause *clause;
4749                 GSList *old_list = finally_ips;
4750                 MonoMethod *method = frame->runtime_method->method;
4751                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4752                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4753                 
4754 #if DEBUG_INTERP
4755                 if (tracing)
4756                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
4757 #endif
4758                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
4759                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
4760                         goto exit_frame;
4761                 }
4762                 ip_offset = frame->ip - rtm->code;
4763
4764                 if (endfinally_ip != NULL)
4765                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
4766                 for (i = 0; i < header->num_clauses; ++i)
4767                         if (frame->ex_handler == &rtm->clauses [i])
4768                                 break;
4769                 while (i > 0) {
4770                         --i;
4771                         clause = &rtm->clauses [i];
4772                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
4773                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
4774                                         ip = rtm->code + clause->handler_offset;
4775                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
4776 #if DEBUG_INTERP
4777                                         if (tracing)
4778                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
4779 #endif
4780                                 }
4781                         }
4782                 }
4783
4784                 endfinally_ip = NULL;
4785
4786                 if (old_list != finally_ips && finally_ips) {
4787                         ip = finally_ips->data;
4788                         finally_ips = g_slist_remove (finally_ips, ip);
4789                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
4790                         goto main_loop;
4791                 }
4792
4793                 /*
4794                  * If an exception is set, we need to execute the fault handler, too,
4795                  * otherwise, we continue normally.
4796                  */
4797                 if (frame->ex)
4798                         goto handle_fault;
4799                 ves_abort();
4800         }
4801         handle_fault:
4802         {
4803                 int i;
4804                 guint32 ip_offset;
4805                 MonoExceptionClause *clause;
4806                 MonoMethod *method = frame->runtime_method->method;
4807                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4808                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4809                 
4810 #if DEBUG_INTERP
4811                 if (tracing)
4812                         g_print ("* Handle fault\n");
4813 #endif
4814                 ip_offset = frame->ip - rtm->code;
4815                 for (i = 0; i < header->num_clauses; ++i) {
4816                         clause = &rtm->clauses [i];
4817                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4818                                 ip = rtm->code + clause->handler_offset;
4819 #if DEBUG_INTERP
4820                                 if (tracing)
4821                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
4822 #endif
4823                                 goto main_loop;
4824                         }
4825                 }
4826                 /*
4827                  * If the handler for the exception was found in this method, we jump
4828                  * to it right away, otherwise we return and let the caller run
4829                  * the finally, fault and catch blocks.
4830                  * This same code should be present in the endfault opcode, but it
4831                  * is corrently not assigned in the ECMA specs: LAMESPEC.
4832                  */
4833                 if (frame->ex_handler) {
4834 #if DEBUG_INTERP
4835                         if (tracing)
4836                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
4837 #endif
4838                         ip = rtm->code + frame->ex_handler->handler_offset;
4839                         sp = frame->stack;
4840                         vt_sp = (unsigned char *) sp + rtm->stack_size;
4841                         sp->data.p = frame->ex;
4842                         ++sp;
4843                         goto main_loop;
4844                 }
4845                 goto exit_frame;
4846         }
4847 exit_frame:
4848         DEBUG_LEAVE ();
4849 }
4850
4851 static void
4852 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
4853 {
4854         ves_exec_method_with_context_with_ip (frame, context, NULL, NULL);
4855 }
4856
4857 void
4858 ves_exec_method (MonoInvocation *frame)
4859 {
4860         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
4861         ThreadContext context_struct;
4862         MonoError error;
4863         jmp_buf env;
4864
4865         frame->ex = NULL;
4866
4867         if (setjmp(env)) {
4868                 mono_unhandled_exception ((MonoObject*)frame->ex);
4869                 return;
4870         }
4871         if (context == NULL) {
4872                 context = &context_struct;
4873                 context_struct.domain = mono_domain_get ();
4874                 context_struct.base_frame = frame;
4875                 context_struct.current_frame = NULL;
4876                 context_struct.env_frame = frame;
4877                 context_struct.current_env = &env;
4878                 context_struct.search_for_handler = 0;
4879                 context_struct.managed_code = 0;
4880                 mono_native_tls_set_value (thread_context_id, context);
4881         }
4882         frame->ip = NULL;
4883         frame->parent = context->current_frame;
4884         frame->runtime_method = mono_interp_get_runtime_method (context->domain, frame->method, &error);
4885         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4886         context->managed_code = 1;
4887         ves_exec_method_with_context (frame, context);
4888         context->managed_code = 0;
4889         if (frame->ex) {
4890                 if (context != &context_struct && context->current_env) {
4891                         context->env_frame->ex = frame->ex;
4892                         longjmp (*context->current_env, 1);
4893                 }
4894                 else
4895                         mono_unhandled_exception ((MonoObject*)frame->ex);
4896         }
4897         if (context->base_frame == frame)
4898                 mono_native_tls_set_value (thread_context_id, NULL);
4899         else
4900                 context->current_frame = frame->parent;
4901 }
4902
4903 static int 
4904 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4905 {
4906         MonoImage *image = mono_assembly_get_image (assembly);
4907         MonoMethod *method;
4908         MonoError error;
4909         int rval;
4910
4911         method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, &error);
4912         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4913
4914         if (!method)
4915                 g_error ("No entry point method found in %s", mono_image_get_filename (image));
4916
4917         rval = mono_runtime_run_main_checked (method, argc, argv, &error);
4918         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4919         return rval;
4920 }
4921
4922 static void
4923 usage (void)
4924 {
4925         fprintf (stderr,
4926                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4927                  "Usage is: mint [options] executable args...\n\n", VERSION);
4928         fprintf (stderr,
4929                  "Runtime Debugging:\n"
4930 #ifdef DEBUG_INTERP
4931                  "   --debug\n"
4932 #endif
4933                  "   --dieonex\n"
4934                  "   --noptr\t\t\tdon't print pointer addresses in trace output\n"
4935                  "   --opcode-count\n"
4936                  "   --print-vtable\n"
4937                  "   --traceclassinit\n"
4938                  "\n"
4939                  "Development:\n"
4940                  "   --debug method_name\n"
4941                  "   --profile\n"
4942                  "   --trace\n"
4943                  "   --traceops\n"
4944                  "   --regression\n"
4945                  "\n"
4946                  "Runtime:\n"
4947                  "   --config filename  load the specified config file instead of the default\n"
4948                  "   --workers n        maximum number of worker threads\n"
4949                 );
4950         exit (1);
4951 }
4952
4953 static MonoBoolean
4954 interp_ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
4955                           MonoReflectionMethod **method, 
4956                           gint32 *iloffset, gint32 *native_offset,
4957                           MonoString **file, gint32 *line, gint32 *column)
4958 {
4959         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
4960         MonoInvocation *inv = context->current_frame;
4961         MonoError error;
4962         int i;
4963
4964         for (i = 0; inv && i < skip; inv = inv->parent)
4965                 if (inv->runtime_method != NULL)
4966                         ++i;
4967
4968         if (iloffset)
4969                 *iloffset = 0;
4970         if (native_offset)
4971                 *native_offset = 0;
4972         if (method) {
4973                 if (inv == NULL) {
4974                         *method = NULL;
4975                 } else {
4976                         *method = mono_method_get_object_checked (context->domain, inv->runtime_method->method, NULL, &error);
4977                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4978                 }
4979         }
4980         if (line)
4981                 *line = 0;
4982         if (need_file_info) {
4983                 if (column)
4984                         *column = 0;
4985                 if (file)
4986                         *file = mono_string_new (mono_domain_get (), "unknown");
4987         }
4988
4989         return TRUE;
4990 }
4991
4992 static MonoArray *
4993 interp_ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
4994 {
4995         MonoDomain *domain = mono_domain_get ();
4996         MonoArray *res;
4997         MonoArray *ta = exc->trace_ips;
4998         MonoError error;
4999         int i, len;
5000
5001         if (ta == NULL) {
5002                 /* Exception is not thrown yet */
5003                 MonoArray *array = mono_array_new_checked (domain, mono_defaults.stack_frame_class, 0, &error);
5004                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5005                 return array;
5006         }
5007         
5008         len = mono_array_length (ta);
5009
5010         res = mono_array_new_checked (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0, &error);
5011         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5012
5013         for (i = skip; i < len / 2; i++) {
5014                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
5015                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5016                 gushort *ip = mono_array_get (ta, gpointer, 2 * i + 1);
5017                 RuntimeMethod *rtm = mono_array_get (ta, gpointer, 2 * i);
5018
5019                 if (rtm != NULL) {
5020                         sf->method = mono_method_get_object_checked (domain, rtm->method, NULL, &error);
5021                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
5022                         sf->native_offset = ip - rtm->code;
5023                 }
5024
5025 #if 0
5026                 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
5027
5028                 if (need_file_info) {
5029                         gchar *filename;
5030                         
5031                         filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
5032
5033                         sf->filename = filename? mono_string_new (domain, filename): NULL;
5034                         sf->column = 0;
5035
5036                         g_free (filename);
5037                 }
5038 #endif
5039
5040                 mono_array_set (res, gpointer, i, sf);
5041         }
5042
5043         return res;
5044 }
5045
5046 void
5047 mono_interp_parse_options (const char *options)
5048 {
5049         char **args, **ptr;
5050
5051         args = g_strsplit (options, ",", -1);
5052         for (ptr = args; ptr && *ptr; ptr ++) {
5053                 char *arg = *ptr;
5054
5055                 if (strncmp (arg, "jit=", 4) == 0)
5056                         jit_classes = g_slist_prepend (jit_classes, arg + 4);
5057         }
5058 }
5059
5060 void
5061 mono_interp_init ()
5062 {
5063         mono_native_tls_alloc (&thread_context_id, NULL);
5064         mono_native_tls_set_value (thread_context_id, NULL);
5065
5066         mono_interp_transform_init ();
5067 }
5068
5069 typedef int (*TestMethod) (void);
5070
5071 static void
5072 interp_regression_step (MonoImage *image, int verbose, int *total_run, int *total, GTimer *timer, MonoDomain *domain)
5073 {
5074         int result, expected, failed, cfailed, run;
5075         double elapsed, transform_time;
5076         int i;
5077         MonoObject *result_obj;
5078         static gboolean filter_method_init = FALSE;
5079         static const char *filter_method = NULL;
5080
5081         g_print ("Test run: image=%s\n", mono_image_get_filename (image));
5082         cfailed = failed = run = 0;
5083         transform_time = elapsed = 0.0;
5084
5085         g_timer_start (timer);
5086         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5087                 MonoObject *exc = NULL;
5088                 MonoError error;
5089                 MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5090                 if (!method) {
5091                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
5092                         continue;
5093                 }
5094
5095                 if (!filter_method_init) {
5096                         filter_method = g_getenv ("INTERP_FILTER_METHOD");
5097                         filter_method_init = TRUE;
5098                 }
5099                 gboolean filter = FALSE;
5100                 if (filter_method) {
5101                         const char *name = filter_method;
5102
5103                         if ((strchr (name, '.') > name) || strchr (name, ':')) {
5104                                 MonoMethodDesc *desc = mono_method_desc_new (name, TRUE);
5105                                 filter = mono_method_desc_full_match (desc, method);
5106                                 mono_method_desc_free (desc);
5107                         } else {
5108                                 filter = strcmp (method->name, name) == 0;
5109                         }
5110                 } else { /* no filter, check for `Category' attribute on method */
5111                         filter = TRUE;
5112                         MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
5113                         mono_error_cleanup (&error);
5114
5115                         if (ainfo) {
5116                                 int j;
5117                                 for (j = 0; j < ainfo->num_attrs && filter; ++j) {
5118                                         MonoCustomAttrEntry *centry = &ainfo->attrs [j];
5119                                         if (centry->ctor == NULL)
5120                                                 continue;
5121
5122                                         MonoClass *klass = centry->ctor->klass;
5123                                         if (strcmp (klass->name, "CategoryAttribute"))
5124                                                 continue;
5125
5126                                         MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
5127                                         /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
5128                                          * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
5129                                         mono_error_cleanup (&error);
5130                                         MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
5131                                         MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
5132                                         mono_error_cleanup (&error);
5133                                         char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
5134                                         mono_error_cleanup (&error);
5135                                         if (!strcmp (utf8_str, "!INTERPRETER")) {
5136                                                 g_print ("skip %s...\n", method->name);
5137                                                 filter = FALSE;
5138                                         }
5139                                 }
5140                         }
5141                 }
5142                 if (strncmp (method->name, "test_", 5) == 0 && filter) {
5143                         MonoError interp_error;
5144                         MonoObject *exc = NULL;
5145
5146                         result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
5147                         if (!mono_error_ok (&interp_error)) {
5148                                 cfailed++;
5149                                 g_print ("Test '%s' execution failed.\n", method->name);
5150                         } else if (exc != NULL) {
5151                                 g_print ("Exception in Test '%s' occured:\n", method->name);
5152                                 mono_object_describe (exc);
5153                                 run++;
5154                                 failed++;
5155                         } else {
5156                                 result = *(gint32 *) mono_object_unbox (result_obj);
5157                                 expected = atoi (method->name + 5);  // FIXME: oh no.
5158                                 run++;
5159
5160                                 if (result != expected) {
5161                                         failed++;
5162                                         g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
5163                                 }
5164                         }
5165                 }
5166         }
5167         g_timer_stop (timer);
5168         elapsed = g_timer_elapsed (timer, NULL);
5169         if (failed > 0 || cfailed > 0){
5170                 g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
5171                                 run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
5172         } else {
5173                 g_print ("Results: total tests: %d, all pass \n",  run);
5174         }
5175
5176         g_print ("Elapsed time: %f secs (%f, %f)\n\n", elapsed,
5177                         elapsed - transform_time, transform_time);
5178         *total += failed + cfailed;
5179         *total_run += run;
5180 }
5181
5182 static int
5183 interp_regression (MonoImage *image, int verbose, int *total_run)
5184 {
5185         MonoMethod *method;
5186         GTimer *timer = g_timer_new ();
5187         MonoDomain *domain = mono_domain_get ();
5188         guint32 i;
5189         int total;
5190
5191         /* load the metadata */
5192         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
5193                 MonoError error;
5194                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
5195                 if (!method) {
5196                         mono_error_cleanup (&error);
5197                         continue;
5198                 }
5199                 mono_class_init (method->klass);
5200         }
5201
5202         total = 0;
5203         *total_run = 0;
5204         interp_regression_step (image, verbose, total_run, &total, timer, domain);
5205
5206         g_timer_destroy (timer);
5207         return total;
5208 }
5209
5210 int
5211 mono_interp_regression_list (int verbose, int count, char *images [])
5212 {
5213         int i, total, total_run, run;
5214         
5215         total_run = total = 0;
5216         for (i = 0; i < count; ++i) {
5217                 MonoAssembly *ass = mono_assembly_open_predicate (images [i], FALSE, FALSE, NULL, NULL, NULL);
5218                 if (!ass) {
5219                         g_warning ("failed to load assembly: %s", images [i]);
5220                         continue;
5221                 }
5222                 total += interp_regression (mono_assembly_get_image (ass), verbose, &run);
5223                 total_run += run;
5224         }
5225         if (total > 0) {
5226                 g_print ("Overall results: tests: %d, failed: %d (pass: %.2f%%)\n", total_run, total, 100.0*(total_run-total)/total_run);
5227         } else {
5228                 g_print ("Overall results: tests: %d, 100%% pass\n", total_run);
5229         }
5230         
5231         return total;
5232 }
5233