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