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