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