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