Merge pull request #4540 from kumpera/android-changes-part1
[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_R4:
1359                         args [a_index].data.f = *(gfloat *) params [i];
1360                         break;
1361                 case MONO_TYPE_R8:
1362                         args [a_index].data.f = *(gdouble *) params [i];
1363                         break;
1364                 case MONO_TYPE_VALUETYPE:
1365                         if (sig->params [i]->data.klass->enumtype) {
1366                                 type = mono_class_enum_basetype (sig->params [i]->data.klass)->type;
1367                                 goto handle_enum;
1368                         } else {
1369                                 args [a_index].data.p = params [i];
1370                         }
1371                         break;
1372                 case MONO_TYPE_STRING:
1373                 case MONO_TYPE_PTR:
1374                 case MONO_TYPE_CLASS:
1375                 case MONO_TYPE_ARRAY:
1376                 case MONO_TYPE_SZARRAY:
1377                 case MONO_TYPE_OBJECT:
1378                 case MONO_TYPE_GENERICINST:
1379                         args [a_index].data.p = params [i];
1380                         break;
1381                 default:
1382                         g_error ("type 0x%x not handled in  runtime invoke", sig->params [i]->type);
1383                 }
1384         }
1385
1386         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
1387                 method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
1388         INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
1389         if (exc)
1390                 frame.invoke_trap = 1;
1391         context->managed_code = 1;
1392         ves_exec_method_with_context (&frame, context);
1393         context->managed_code = 0;
1394         if (context == &context_struct)
1395                 mono_native_tls_set_value (thread_context_id, NULL);
1396         else
1397                 context->current_frame = old_frame;
1398         if (frame.ex != NULL) {
1399                 if (exc != NULL) {
1400                         *exc = (MonoObject*) frame.ex;
1401                         return NULL;
1402                 }
1403                 if (context->current_env != NULL) {
1404                         context->env_frame->ex = frame.ex;
1405                         longjmp(*context->current_env, 1);
1406                 }
1407                 else
1408                         printf("dropped exception...\n");
1409         }
1410         if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
1411                 return NULL;
1412         if (isobject || method->string_ctor)
1413                 return result.data.p;
1414         stackval_to_data (sig->ret, &result, ret, sig->pinvoke);
1415         return retval;
1416 }
1417
1418 static stackval * 
1419 do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
1420 {
1421         MonoInvocation *old_frame = context->current_frame;
1422         MonoInvocation *old_env_frame = context->env_frame;
1423         jmp_buf *old_env = context->current_env;
1424         jmp_buf env;
1425
1426         if (setjmp (env)) {
1427                 context->current_frame = old_frame;
1428                 context->env_frame = old_env_frame;
1429                 context->current_env = old_env;
1430                 context->managed_code = 1;
1431                 return sp;
1432         }
1433
1434         context->env_frame = context->current_frame;
1435         context->current_env = &env;
1436         context->managed_code = 0;
1437
1438         switch (op) {
1439         case MINT_ICALL_V_V: {
1440                 void (*func)() = ptr;
1441                 func ();
1442                 break;
1443         }
1444         case MINT_ICALL_V_P: {
1445                 gpointer (*func)() = ptr;
1446                 sp++;
1447                 sp [-1].data.p = func ();
1448                 break;
1449         }
1450         case MINT_ICALL_P_V: {
1451                 void (*func)(gpointer) = ptr;
1452                 func (sp [-1].data.p);
1453                 sp --;
1454                 break;
1455         }
1456         case MINT_ICALL_P_P: {
1457                 gpointer (*func)(gpointer) = ptr;
1458                 sp [-1].data.p = func (sp [-1].data.p);
1459                 break;
1460         }
1461         case MINT_ICALL_PP_V: {
1462                 void (*func)(gpointer,gpointer) = ptr;
1463                 sp -= 2;
1464                 func (sp [0].data.p, sp [1].data.p);
1465                 break;
1466         }
1467         case MINT_ICALL_PI_V: {
1468                 void (*func)(gpointer,int) = ptr;
1469                 sp -= 2;
1470                 func (sp [0].data.p, sp [1].data.i);
1471                 break;
1472         }
1473         case MINT_ICALL_PP_P: {
1474                 gpointer (*func)(gpointer,gpointer) = ptr;
1475                 --sp;
1476                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
1477                 break;
1478         }
1479         case MINT_ICALL_PI_P: {
1480                 gpointer (*func)(gpointer,int) = ptr;
1481                 --sp;
1482                 sp [-1].data.p = func (sp [-1].data.p, sp [0].data.i);
1483                 break;
1484         }
1485         case MINT_ICALL_PPP_V: {
1486                 void (*func)(gpointer,gpointer,gpointer) = ptr;
1487                 sp -= 3;
1488                 func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
1489                 break;
1490         }
1491         case MINT_ICALL_PPI_V: {
1492                 void (*func)(gpointer,gpointer,int) = ptr;
1493                 sp -= 3;
1494                 func (sp [0].data.p, sp [1].data.p, sp [2].data.i);
1495                 break;
1496         }
1497         default:
1498                 g_assert_not_reached ();
1499         }
1500
1501         context->env_frame = old_env_frame;
1502         context->current_env = old_env;
1503
1504         return sp;
1505 }
1506
1507 static mono_mutex_t create_method_pointer_mutex;
1508
1509 static GHashTable *method_pointer_hash = NULL;
1510
1511 #define TRAMPS_USED 8
1512
1513 static MonoMethod *method_pointers [TRAMPS_USED] = {0};
1514
1515 #define GEN_METHOD_PTR_TRAMP(num) \
1516                 static MonoObject * mp_tramp_ ## num (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) { \
1517                         MonoError error; \
1518                         void *params_real[] = {this_obj, &params, &exc, &compiled_method}; \
1519                         MonoObject *ret = mono_interp_runtime_invoke (method_pointers [num], NULL, params_real, NULL, &error); \
1520                         mono_error_cleanup (&error); \
1521                         return ret; \
1522                 }
1523
1524
1525 GEN_METHOD_PTR_TRAMP (0);
1526 GEN_METHOD_PTR_TRAMP (1);
1527 GEN_METHOD_PTR_TRAMP (2);
1528 GEN_METHOD_PTR_TRAMP (3);
1529 GEN_METHOD_PTR_TRAMP (4);
1530 GEN_METHOD_PTR_TRAMP (5);
1531 GEN_METHOD_PTR_TRAMP (6);
1532 GEN_METHOD_PTR_TRAMP (7);
1533
1534 #undef GEN_METHOD_PTR_TRAMP
1535
1536 gpointer *mp_tramps[TRAMPS_USED] = {
1537         (gpointer) mp_tramp_0, (gpointer) mp_tramp_1, (gpointer) mp_tramp_2, (gpointer) mp_tramp_3,
1538         (gpointer) mp_tramp_4, (gpointer) mp_tramp_5, (gpointer) mp_tramp_6, (gpointer) mp_tramp_7
1539 };
1540
1541 static int tramps_used = 0;
1542
1543 gpointer
1544 mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
1545 {
1546         gpointer addr;
1547         MonoJitInfo *ji;
1548
1549         mono_os_mutex_lock (&create_method_pointer_mutex);
1550         if (!method_pointer_hash) {
1551                 // FIXME: is registering method table as GC root really necessary?
1552                 // MONO_GC_REGISTER_ROOT_FIXED (method_pointer_hash);
1553                 method_pointer_hash = g_hash_table_new (NULL, NULL);
1554         }
1555         addr = g_hash_table_lookup (method_pointer_hash, method);
1556         if (addr) {
1557                 mono_os_mutex_unlock (&create_method_pointer_mutex);
1558                 return addr;
1559         }
1560
1561         /*
1562          * If it is a static P/Invoke method, we can just return the pointer
1563          * to the method implementation.
1564          */
1565         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) {
1566                 ji = g_new0 (MonoJitInfo, 1);
1567                 ji->d.method = method;
1568                 ji->code_size = 1;
1569                 ji->code_start = addr = ((MonoMethodPInvoke*) method)->addr;
1570
1571                 mono_jit_info_table_add (mono_get_root_domain (), ji);
1572         }               
1573         else {
1574                 g_assert (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE);
1575                 g_assert (tramps_used < TRAMPS_USED);
1576
1577                 /* FIXME: needs locking */
1578                 method_pointers [tramps_used] = method;
1579                 addr = mp_tramps [tramps_used];
1580                 tramps_used++;
1581         }
1582
1583         g_hash_table_insert (method_pointer_hash, method, addr);
1584         mono_os_mutex_unlock (&create_method_pointer_mutex);
1585
1586         return addr;
1587 }
1588
1589 #if COUNT_OPS
1590 static int opcode_counts[512];
1591
1592 #define COUNT_OP(op) opcode_counts[op]++
1593 #else
1594 #define COUNT_OP(op) 
1595 #endif
1596
1597 #if DEBUG_INTERP
1598 #define DUMP_INSTR() \
1599         if (tracing > 1) { \
1600                 char *ins; \
1601                 if (sp > frame->stack) { \
1602                         ins = dump_stack (frame->stack, sp); \
1603                 } else { \
1604                         ins = g_strdup (""); \
1605                 } \
1606                 sp->data.l = 0; \
1607                 output_indent (); \
1608                 char *mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
1609                 g_print ("(%p) %s -> ", mono_thread_internal_current (), mn); \
1610                 g_free (mn); \
1611                 mono_interp_dis_mintop(rtm->code, ip); \
1612                 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
1613                 g_free (ins); \
1614         }
1615 #else
1616 #define DUMP_INSTR()
1617 #endif
1618
1619 #ifdef __GNUC__
1620 #define USE_COMPUTED_GOTO 1
1621 #endif
1622 #if USE_COMPUTED_GOTO
1623 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
1624 #define MINT_IN_CASE(x) LAB_ ## x:
1625 #if DEBUG_INTERP
1626 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
1627 #else
1628 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
1629 #endif
1630 #define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
1631 #else
1632 #define MINT_IN_SWITCH(op) switch (op)
1633 #define MINT_IN_CASE(x) case x:
1634 #define MINT_IN_BREAK break
1635 #define MINT_IN_DEFAULT default:
1636 #endif
1637
1638 static void 
1639 ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
1640 {
1641         MonoInvocation child_frame;
1642         GSList *finally_ips = NULL;
1643         const unsigned short *endfinally_ip = NULL;
1644         const unsigned short *ip = NULL;
1645         register stackval *sp;
1646         RuntimeMethod *rtm;
1647 #if DEBUG_INTERP
1648         gint tracing = global_tracing;
1649         unsigned char *vtalloc;
1650 #endif
1651         int i32;
1652         unsigned char *vt_sp;
1653         unsigned char *locals;
1654         MonoError error;
1655         MonoObject *o = NULL;
1656         MonoClass *c;
1657 #if USE_COMPUTED_GOTO
1658         static void *in_labels[] = {
1659 #define OPDEF(a,b,c,d) \
1660         &&LAB_ ## a,
1661 #include "mintops.def"
1662         0 };
1663 #endif
1664
1665         frame->ex = NULL;
1666         frame->ex_handler = NULL;
1667         frame->ip = NULL;
1668         context->current_frame = frame;
1669
1670 #if DEBUG_INTERP
1671         debug_enter (frame, &tracing);
1672 #endif
1673
1674         if (!frame->runtime_method->transformed) {
1675                 context->managed_code = 0;
1676 #if DEBUG_INTERP
1677                 char *mn = mono_method_full_name (frame->runtime_method->method, TRUE);
1678                 g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn);
1679                 g_free (mn);
1680 #endif
1681                 frame->ex = mono_interp_transform_method (frame->runtime_method, context);
1682                 context->managed_code = 1;
1683                 if (frame->ex) {
1684                         rtm = NULL;
1685                         ip = NULL;
1686                         goto exit_frame;
1687                 }
1688         }
1689
1690         rtm = frame->runtime_method;
1691         frame->args = alloca (rtm->alloca_size);
1692         memset (frame->args, 0, rtm->alloca_size);
1693
1694         sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
1695         memset (sp, 0, rtm->stack_size);
1696
1697         vt_sp = (unsigned char *) sp + rtm->stack_size;
1698         memset (vt_sp, 0, rtm->vt_stack_size);
1699 #if DEBUG_INTERP
1700         vtalloc = vt_sp;
1701 #endif
1702
1703         locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
1704         memset (vt_sp, 0, rtm->locals_size);
1705
1706         child_frame.parent = frame;
1707
1708         /* ready to go */
1709         ip = rtm->code;
1710
1711         /*
1712          * using while (ip < end) may result in a 15% performance drop, 
1713          * but it may be useful for debug
1714          */
1715         while (1) {
1716         main_loop:
1717                 /* g_assert (sp >= frame->stack); */
1718                 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
1719                 DUMP_INSTR();
1720                 MINT_IN_SWITCH (*ip) {
1721                 MINT_IN_CASE(MINT_INITLOCALS)
1722                         memset (locals, 0, rtm->locals_size);
1723                         ++ip;
1724                         MINT_IN_BREAK;
1725                 MINT_IN_CASE(MINT_NOP)
1726                         ++ip;
1727                         MINT_IN_BREAK;
1728                 MINT_IN_CASE(MINT_BREAK)
1729                         ++ip;
1730                         G_BREAKPOINT (); /* this is not portable... */
1731                         MINT_IN_BREAK;
1732                 MINT_IN_CASE(MINT_LDNULL) 
1733                         sp->data.p = NULL;
1734                         ++ip;
1735                         ++sp;
1736                         MINT_IN_BREAK;
1737                 MINT_IN_CASE(MINT_VTRESULT) {
1738                         int ret_size = * (guint16 *)(ip + 1);
1739                         unsigned char *ret_vt_sp = vt_sp;
1740                         vt_sp -= READ32(ip + 2);
1741                         if (ret_size > 0) {
1742                                 memmove (vt_sp, ret_vt_sp, ret_size);
1743                                 sp [-1].data.p = vt_sp;
1744                                 vt_sp += (ret_size + 7) & ~7;
1745                         }
1746                         ip += 4;
1747                         MINT_IN_BREAK;
1748                 }
1749 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
1750                 MINT_IN_CASE(MINT_LDC_I4_M1)
1751                         LDC(-1);
1752                         MINT_IN_BREAK;
1753                 MINT_IN_CASE(MINT_LDC_I4_0)
1754                         LDC(0);
1755                         MINT_IN_BREAK;
1756                 MINT_IN_CASE(MINT_LDC_I4_1)
1757                         LDC(1);
1758                         MINT_IN_BREAK;
1759                 MINT_IN_CASE(MINT_LDC_I4_2)
1760                         LDC(2);
1761                         MINT_IN_BREAK;
1762                 MINT_IN_CASE(MINT_LDC_I4_3)
1763                         LDC(3);
1764                         MINT_IN_BREAK;
1765                 MINT_IN_CASE(MINT_LDC_I4_4)
1766                         LDC(4);
1767                         MINT_IN_BREAK;
1768                 MINT_IN_CASE(MINT_LDC_I4_5)
1769                         LDC(5);
1770                         MINT_IN_BREAK;
1771                 MINT_IN_CASE(MINT_LDC_I4_6)
1772                         LDC(6);
1773                         MINT_IN_BREAK;
1774                 MINT_IN_CASE(MINT_LDC_I4_7)
1775                         LDC(7);
1776                         MINT_IN_BREAK;
1777                 MINT_IN_CASE(MINT_LDC_I4_8)
1778                         LDC(8);
1779                         MINT_IN_BREAK;
1780                 MINT_IN_CASE(MINT_LDC_I4_S) 
1781                         sp->data.i = *(const short *)(ip + 1);
1782                         ip += 2;
1783                         ++sp;
1784                         MINT_IN_BREAK;
1785                 MINT_IN_CASE(MINT_LDC_I4)
1786                         ++ip;
1787                         sp->data.i = READ32 (ip);
1788                         ip += 2;
1789                         ++sp;
1790                         MINT_IN_BREAK;
1791                 MINT_IN_CASE(MINT_LDC_I8)
1792                         ++ip;
1793                         sp->data.l = READ64 (ip);
1794                         ip += 4;
1795                         ++sp;
1796                         MINT_IN_BREAK;
1797                 MINT_IN_CASE(MINT_LDC_R4) {
1798                         guint32 val;
1799                         ++ip;
1800                         val = READ32(ip);
1801                         sp->data.f = * (float *)&val;
1802                         ip += 2;
1803                         ++sp;
1804                         MINT_IN_BREAK;
1805                 }
1806                 MINT_IN_CASE(MINT_LDC_R8) 
1807                         sp->data.l = READ64 (ip + 1); /* note union usage */
1808                         ip += 5;
1809                         ++sp;
1810                         MINT_IN_BREAK;
1811                 MINT_IN_CASE(MINT_DUP) 
1812                         sp [0] = sp[-1];
1813                         ++sp;
1814                         ++ip; 
1815                         MINT_IN_BREAK;
1816                 MINT_IN_CASE(MINT_DUP_VT)
1817                         i32 = READ32 (ip + 1);
1818                         sp->data.p = vt_sp;
1819                         memcpy(sp->data.p, sp [-1].data.p, i32);
1820                         vt_sp += (i32 + 7) & ~7;
1821                         ++sp;
1822                         ip += 3;
1823                         MINT_IN_BREAK;
1824                 MINT_IN_CASE(MINT_POP) {
1825                         guint16 u16 = (* (guint16 *)(ip + 1)) + 1;
1826                         if (u16 > 1)
1827                                 memmove (sp - u16, sp - 1, (u16 - 1) * sizeof (stackval));
1828                         sp--;
1829                         ip += 2;
1830                         MINT_IN_BREAK;
1831                 }
1832                 MINT_IN_CASE(MINT_JMP) {
1833                         RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
1834                         if (!new_method->transformed) {
1835                                 frame->ip = ip;
1836                                 frame->ex = mono_interp_transform_method (new_method, context);
1837                                 if (frame->ex)
1838                                         goto exit_frame;
1839                         }
1840                         ip += 2;
1841                         if (new_method->alloca_size > rtm->alloca_size)
1842                                 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size); 
1843                         rtm = frame->runtime_method = new_method;
1844                         vt_sp = (unsigned char *) sp + rtm->stack_size;
1845 #if DEBUG_INTERP
1846                         vtalloc = vt_sp;
1847 #endif
1848                         locals = vt_sp + rtm->vt_stack_size;
1849                         ip = rtm->new_body_start; /* bypass storing input args from callers frame */
1850                         MINT_IN_BREAK;
1851                 }
1852                 MINT_IN_CASE(MINT_CALLI) {
1853                         MonoMethodSignature *csignature;
1854                         stackval *endsp = sp;
1855
1856                         frame->ip = ip;
1857                         
1858                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1859                         ip += 2;
1860                         --sp;
1861                         --endsp;
1862                         child_frame.runtime_method = sp->data.p;
1863
1864                         sp->data.p = vt_sp;
1865                         child_frame.retval = sp;
1866                         /* decrement by the actual number of args */
1867                         sp -= csignature->param_count;
1868                         if (csignature->hasthis)
1869                                 --sp;
1870                         child_frame.stack_args = sp;
1871
1872                         /* `this' can be NULL for string:.ctor */
1873                         if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
1874                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
1875                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1876                         } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1877                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
1878                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1879                         }
1880
1881                         if (csignature->hasthis) {
1882                                 MonoObject *this_arg = sp->data.p;
1883
1884                                 if (this_arg->vtable->klass->valuetype) {
1885                                         gpointer *unboxed = mono_object_unbox (this_arg);
1886                                         sp [0].data.p = unboxed;
1887                                 }
1888                         }
1889
1890                         ves_exec_method_with_context (&child_frame, context);
1891
1892                         context->current_frame = frame;
1893
1894                         if (child_frame.ex) {
1895                                 /*
1896                                  * An exception occurred, need to run finally, fault and catch handlers..
1897                                  */
1898                                 frame->ex = child_frame.ex;
1899                                 goto handle_finally;
1900                         }
1901
1902                         /* need to handle typedbyref ... */
1903                         if (csignature->ret->type != MONO_TYPE_VOID) {
1904                                 *sp = *endsp;
1905                                 sp++;
1906                         }
1907                         MINT_IN_BREAK;
1908                 }
1909                 MINT_IN_CASE(MINT_CALLI_NAT) {
1910                         MonoMethodSignature *csignature;
1911                         stackval *endsp = sp;
1912                         unsigned char *code = NULL;
1913
1914                         frame->ip = ip;
1915                         
1916                         csignature = rtm->data_items [* (guint16 *)(ip + 1)];
1917                         ip += 2;
1918                         --sp;
1919                         --endsp;
1920                         code = sp->data.p;
1921                         child_frame.runtime_method = NULL;
1922
1923                         sp->data.p = vt_sp;
1924                         child_frame.retval = sp;
1925                         /* decrement by the actual number of args */
1926                         sp -= csignature->param_count;
1927                         if (csignature->hasthis)
1928                                 --sp;
1929                         child_frame.stack_args = sp;
1930                         ves_pinvoke_method (&child_frame, csignature, (MonoFuncV) code, FALSE, context);
1931
1932                         context->current_frame = frame;
1933
1934                         if (child_frame.ex) {
1935                                 /*
1936                                  * An exception occurred, need to run finally, fault and catch handlers..
1937                                  */
1938                                 frame->ex = child_frame.ex;
1939                                 if (context->search_for_handler) {
1940                                         context->search_for_handler = 0;
1941                                         goto handle_exception;
1942                                 }
1943                                 goto handle_finally;
1944                         }
1945
1946                         /* need to handle typedbyref ... */
1947                         if (csignature->ret->type != MONO_TYPE_VOID) {
1948                                 *sp = *endsp;
1949                                 sp++;
1950                         }
1951                         MINT_IN_BREAK;
1952                 }
1953                 MINT_IN_CASE(MINT_CALL) {
1954                         stackval *endsp = sp;
1955
1956                         frame->ip = ip;
1957                         
1958                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1959                         ip += 2;
1960                         sp->data.p = vt_sp;
1961                         child_frame.retval = sp;
1962                         /* decrement by the actual number of args */
1963                         sp -= child_frame.runtime_method->param_count;
1964                         if (child_frame.runtime_method->hasthis)
1965                                 --sp;
1966                         child_frame.stack_args = sp;
1967
1968                         /* `this' can be NULL for string:.ctor */
1969                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
1970                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
1971                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1972                         }
1973                         ves_exec_method_with_context (&child_frame, context);
1974
1975                         context->current_frame = frame;
1976
1977                         if (child_frame.ex) {
1978                                 /*
1979                                  * An exception occurred, need to run finally, fault and catch handlers..
1980                                  */
1981                                 frame->ex = child_frame.ex;
1982                                 goto handle_exception;;
1983                         }
1984
1985                         /* need to handle typedbyref ... */
1986                         *sp = *endsp;
1987                         sp++;
1988                         MINT_IN_BREAK;
1989                 }
1990                 MINT_IN_CASE(MINT_VCALL) {
1991                         frame->ip = ip;
1992                         
1993                         child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
1994                         ip += 2;
1995
1996                         sp->data.p = vt_sp;
1997                         child_frame.retval = sp;
1998                         /* decrement by the actual number of args */
1999                         sp -= child_frame.runtime_method->param_count;
2000                         if (child_frame.runtime_method->hasthis) {
2001                                 --sp;
2002                                 MonoObject *this_arg = sp->data.p;
2003                                 if (!this_arg)
2004                                         THROW_EX (mono_get_exception_null_reference(), ip - 2);
2005                         }
2006                         child_frame.stack_args = sp;
2007
2008                         if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
2009                                 child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
2010                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2011                         }
2012
2013                         ves_exec_method_with_context (&child_frame, context);
2014
2015                         context->current_frame = frame;
2016
2017                         if (child_frame.ex) {
2018                                 /*
2019                                  * An exception occurred, need to run finally, fault and catch handlers..
2020                                  */
2021                                 frame->ex = child_frame.ex;
2022                                 goto handle_finally;
2023                         }
2024                         MINT_IN_BREAK;
2025                 }
2026                 MINT_IN_CASE(MINT_CALLVIRT) {
2027                         stackval *endsp = sp;
2028                         MonoObject *this_arg;
2029                         guint32 token;
2030
2031                         frame->ip = ip;
2032                         
2033                         token = * (unsigned short *)(ip + 1);
2034                         ip += 2;
2035                         child_frame.runtime_method = rtm->data_items [token];
2036                         sp->data.p = vt_sp;
2037                         child_frame.retval = sp;
2038
2039                         /* decrement by the actual number of args */
2040                         sp -= child_frame.runtime_method->param_count + 1;
2041                         child_frame.stack_args = sp;
2042                         this_arg = sp->data.p;
2043                         if (!this_arg)
2044                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2045                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2046
2047                         MonoClass *this_class = this_arg->vtable->klass;
2048                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2049                                 /* unbox */
2050                                 gpointer *unboxed = mono_object_unbox (this_arg);
2051                                 sp [0].data.p = unboxed;
2052                         }
2053
2054                         ves_exec_method_with_context (&child_frame, context);
2055
2056                         context->current_frame = frame;
2057
2058                         if (child_frame.ex) {
2059                                 /*
2060                                  * An exception occurred, need to run finally, fault and catch handlers..
2061                                  */
2062                                 frame->ex = child_frame.ex;
2063                                 if (context->search_for_handler) {
2064                                         context->search_for_handler = 0;
2065                                         goto handle_exception;
2066                                 }
2067                                 goto handle_finally;
2068                         }
2069
2070                         /* need to handle typedbyref ... */
2071                         *sp = *endsp;
2072                         sp++;
2073                         MINT_IN_BREAK;
2074                 }
2075                 MINT_IN_CASE(MINT_VCALLVIRT) {
2076                         MonoObject *this_arg;
2077                         guint32 token;
2078
2079                         frame->ip = ip;
2080                         
2081                         token = * (unsigned short *)(ip + 1);
2082                         ip += 2;
2083                         child_frame.runtime_method = rtm->data_items [token];
2084                         sp->data.p = vt_sp;
2085                         child_frame.retval = sp;
2086
2087                         /* decrement by the actual number of args */
2088                         sp -= child_frame.runtime_method->param_count + 1;
2089                         child_frame.stack_args = sp;
2090                         this_arg = sp->data.p;
2091                         if (!this_arg)
2092                                 THROW_EX (mono_get_exception_null_reference(), ip - 2);
2093                         child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
2094
2095                         MonoClass *this_class = this_arg->vtable->klass;
2096                         if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
2097                                 gpointer *unboxed = mono_object_unbox (this_arg);
2098                                 sp [0].data.p = unboxed;
2099                         }
2100
2101                         ves_exec_method_with_context (&child_frame, context);
2102
2103                         context->current_frame = frame;
2104
2105                         if (child_frame.ex) {
2106                                 /*
2107                                  * An exception occurred, need to run finally, fault and catch handlers..
2108                                  */
2109                                 frame->ex = child_frame.ex;
2110                                 if (context->search_for_handler) {
2111                                         context->search_for_handler = 0;
2112                                         goto handle_exception;
2113                                 }
2114                                 goto handle_finally;
2115                         }
2116                         MINT_IN_BREAK;
2117                 }
2118                 MINT_IN_CASE(MINT_CALLRUN)
2119                         ves_runtime_method (frame, context);
2120                         if (frame->ex) {
2121                                 rtm = NULL;
2122                                 goto handle_exception;
2123                         }
2124                         goto exit_frame;
2125                 MINT_IN_CASE(MINT_RET)
2126                         --sp;
2127                         *frame->retval = *sp;
2128                         if (sp > frame->stack)
2129                                 g_warning ("ret: more values on stack: %d", sp-frame->stack);
2130                         goto exit_frame;
2131                 MINT_IN_CASE(MINT_RET_VOID)
2132                         if (sp > frame->stack)
2133                                 g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
2134                         goto exit_frame;
2135                 MINT_IN_CASE(MINT_RET_VT)
2136                         i32 = READ32(ip + 1);
2137                         --sp;
2138                         memcpy(frame->retval->data.p, sp->data.p, i32);
2139                         if (sp > frame->stack)
2140                                 g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
2141                         goto exit_frame;
2142                 MINT_IN_CASE(MINT_BR_S)
2143                         ip += (short) *(ip + 1);
2144                         MINT_IN_BREAK;
2145                 MINT_IN_CASE(MINT_BR)
2146                         ip += (gint32) READ32(ip + 1);
2147                         MINT_IN_BREAK;
2148 #define ZEROP_S(datamem, op) \
2149         --sp; \
2150         if (sp->data.datamem op 0) \
2151                 ip += * (gint16 *)(ip + 1); \
2152         else \
2153                 ip += 2;
2154
2155 #define ZEROP(datamem, op) \
2156         --sp; \
2157         if (sp->data.datamem op 0) \
2158                 ip += READ32(ip + 1); \
2159         else \
2160                 ip += 3;
2161
2162                 MINT_IN_CASE(MINT_BRFALSE_I4_S)
2163                         ZEROP_S(i, ==);
2164                         MINT_IN_BREAK;
2165                 MINT_IN_CASE(MINT_BRFALSE_I8_S)
2166                         ZEROP_S(l, ==);
2167                         MINT_IN_BREAK;
2168                 MINT_IN_CASE(MINT_BRFALSE_R8_S)
2169                         ZEROP_S(f, ==);
2170                         MINT_IN_BREAK;
2171                 MINT_IN_CASE(MINT_BRFALSE_I4)
2172                         ZEROP(i, ==);
2173                         MINT_IN_BREAK;
2174                 MINT_IN_CASE(MINT_BRFALSE_I8)
2175                         ZEROP(l, ==);
2176                         MINT_IN_BREAK;
2177                 MINT_IN_CASE(MINT_BRFALSE_R8)
2178                         ZEROP_S(f, ==);
2179                         MINT_IN_BREAK;
2180                 MINT_IN_CASE(MINT_BRTRUE_I4_S)
2181                         ZEROP_S(i, !=);
2182                         MINT_IN_BREAK;
2183                 MINT_IN_CASE(MINT_BRTRUE_I8_S)
2184                         ZEROP_S(l, !=);
2185                         MINT_IN_BREAK;
2186                 MINT_IN_CASE(MINT_BRTRUE_R8_S)
2187                         ZEROP_S(f, !=);
2188                         MINT_IN_BREAK;
2189                 MINT_IN_CASE(MINT_BRTRUE_I4)
2190                         ZEROP(i, !=);
2191                         MINT_IN_BREAK;
2192                 MINT_IN_CASE(MINT_BRTRUE_I8)
2193                         ZEROP(l, !=);
2194                         MINT_IN_BREAK;
2195                 MINT_IN_CASE(MINT_BRTRUE_R8)
2196                         ZEROP(f, !=);
2197                         MINT_IN_BREAK;
2198 #define CONDBR_S(cond) \
2199         sp -= 2; \
2200         if (cond) \
2201                 ip += * (gint16 *)(ip + 1); \
2202         else \
2203                 ip += 2;
2204 #define BRELOP_S(datamem, op) \
2205         CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
2206
2207 #define CONDBR(cond) \
2208         sp -= 2; \
2209         if (cond) \
2210                 ip += READ32(ip + 1); \
2211         else \
2212                 ip += 3;
2213
2214 #define BRELOP(datamem, op) \
2215         CONDBR(sp[0].data.datamem op sp[1].data.datamem)
2216
2217                 MINT_IN_CASE(MINT_BEQ_I4_S)
2218                         BRELOP_S(i, ==)
2219                         MINT_IN_BREAK;
2220                 MINT_IN_CASE(MINT_BEQ_I8_S)
2221                         BRELOP_S(l, ==)
2222                         MINT_IN_BREAK;
2223                 MINT_IN_CASE(MINT_BEQ_R8_S)
2224                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2225                         MINT_IN_BREAK;
2226                 MINT_IN_CASE(MINT_BEQ_I4)
2227                         BRELOP(i, ==)
2228                         MINT_IN_BREAK;
2229                 MINT_IN_CASE(MINT_BEQ_I8)
2230                         BRELOP(l, ==)
2231                         MINT_IN_BREAK;
2232                 MINT_IN_CASE(MINT_BEQ_R8)
2233                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
2234                         MINT_IN_BREAK;
2235                 MINT_IN_CASE(MINT_BGE_I4_S)
2236                         BRELOP_S(i, >=)
2237                         MINT_IN_BREAK;
2238                 MINT_IN_CASE(MINT_BGE_I8_S)
2239                         BRELOP_S(l, >=)
2240                         MINT_IN_BREAK;
2241                 MINT_IN_CASE(MINT_BGE_R8_S)
2242                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2243                         MINT_IN_BREAK;
2244                 MINT_IN_CASE(MINT_BGE_I4)
2245                         BRELOP(i, >=)
2246                         MINT_IN_BREAK;
2247                 MINT_IN_CASE(MINT_BGE_I8)
2248                         BRELOP(l, >=)
2249                         MINT_IN_BREAK;
2250                 MINT_IN_CASE(MINT_BGE_R8)
2251                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
2252                         MINT_IN_BREAK;
2253                 MINT_IN_CASE(MINT_BGT_I4_S)
2254                         BRELOP_S(i, >)
2255                         MINT_IN_BREAK;
2256                 MINT_IN_CASE(MINT_BGT_I8_S)
2257                         BRELOP_S(l, >)
2258                         MINT_IN_BREAK;
2259                 MINT_IN_CASE(MINT_BGT_R8_S)
2260                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2261                         MINT_IN_BREAK;
2262                 MINT_IN_CASE(MINT_BGT_I4)
2263                         BRELOP(i, >)
2264                         MINT_IN_BREAK;
2265                 MINT_IN_CASE(MINT_BGT_I8)
2266                         BRELOP(l, >)
2267                         MINT_IN_BREAK;
2268                 MINT_IN_CASE(MINT_BGT_R8)
2269                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
2270                         MINT_IN_BREAK;
2271                 MINT_IN_CASE(MINT_BLT_I4_S)
2272                         BRELOP_S(i, <)
2273                         MINT_IN_BREAK;
2274                 MINT_IN_CASE(MINT_BLT_I8_S)
2275                         BRELOP_S(l, <)
2276                         MINT_IN_BREAK;
2277                 MINT_IN_CASE(MINT_BLT_R8_S)
2278                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2279                         MINT_IN_BREAK;
2280                 MINT_IN_CASE(MINT_BLT_I4)
2281                         BRELOP(i, <)
2282                         MINT_IN_BREAK;
2283                 MINT_IN_CASE(MINT_BLT_I8)
2284                         BRELOP(l, <)
2285                         MINT_IN_BREAK;
2286                 MINT_IN_CASE(MINT_BLT_R8)
2287                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
2288                         MINT_IN_BREAK;
2289                 MINT_IN_CASE(MINT_BLE_I4_S)
2290                         BRELOP_S(i, <=)
2291                         MINT_IN_BREAK;
2292                 MINT_IN_CASE(MINT_BLE_I8_S)
2293                         BRELOP_S(l, <=)
2294                         MINT_IN_BREAK;
2295                 MINT_IN_CASE(MINT_BLE_R8_S)
2296                         CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2297                         MINT_IN_BREAK;
2298                 MINT_IN_CASE(MINT_BLE_I4)
2299                         BRELOP(i, <=)
2300                         MINT_IN_BREAK;
2301                 MINT_IN_CASE(MINT_BLE_I8)
2302                         BRELOP(l, <=)
2303                         MINT_IN_BREAK;
2304                 MINT_IN_CASE(MINT_BLE_R8)
2305                         CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
2306                         MINT_IN_BREAK;
2307                 MINT_IN_CASE(MINT_BNE_UN_I4_S)
2308                         BRELOP_S(i, !=)
2309                         MINT_IN_BREAK;
2310                 MINT_IN_CASE(MINT_BNE_UN_I8_S)
2311                         BRELOP_S(l, !=)
2312                         MINT_IN_BREAK;
2313                 MINT_IN_CASE(MINT_BNE_UN_R8_S)
2314                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
2315                         MINT_IN_BREAK;
2316                 MINT_IN_CASE(MINT_BNE_UN_I4)
2317                         BRELOP(i, !=)
2318                         MINT_IN_BREAK;
2319                 MINT_IN_CASE(MINT_BNE_UN_I8)
2320                         BRELOP(l, !=)
2321                         MINT_IN_BREAK;
2322                 MINT_IN_CASE(MINT_BNE_UN_R8)
2323                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
2324                         MINT_IN_BREAK;
2325
2326 #define BRELOP_S_CAST(datamem, op, type) \
2327         sp -= 2; \
2328         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2329                 ip += * (gint16 *)(ip + 1); \
2330         else \
2331                 ip += 2;
2332
2333 #define BRELOP_CAST(datamem, op, type) \
2334         sp -= 2; \
2335         if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2336                 ip += READ32(ip + 1); \
2337         else \
2338                 ip += 3;
2339
2340                 MINT_IN_CASE(MINT_BGE_UN_I4_S)
2341                         BRELOP_S_CAST(i, >=, guint32);
2342                         MINT_IN_BREAK;
2343                 MINT_IN_CASE(MINT_BGE_UN_I8_S)
2344                         BRELOP_S_CAST(l, >=, guint64);
2345                         MINT_IN_BREAK;
2346                 MINT_IN_CASE(MINT_BGE_UN_R8_S)
2347                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2348                         MINT_IN_BREAK;
2349                 MINT_IN_CASE(MINT_BGE_UN_I4)
2350                         BRELOP_CAST(i, >=, guint32);
2351                         MINT_IN_BREAK;
2352                 MINT_IN_CASE(MINT_BGE_UN_I8)
2353                         BRELOP_CAST(l, >=, guint64);
2354                         MINT_IN_BREAK;
2355                 MINT_IN_CASE(MINT_BGE_UN_R8)
2356                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
2357                         MINT_IN_BREAK;
2358                 MINT_IN_CASE(MINT_BGT_UN_I4_S)
2359                         BRELOP_S_CAST(i, >, guint32);
2360                         MINT_IN_BREAK;
2361                 MINT_IN_CASE(MINT_BGT_UN_I8_S)
2362                         BRELOP_S_CAST(l, >, guint64);
2363                         MINT_IN_BREAK;
2364                 MINT_IN_CASE(MINT_BGT_UN_R8_S)
2365                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2366                         MINT_IN_BREAK;
2367                 MINT_IN_CASE(MINT_BGT_UN_I4)
2368                         BRELOP_CAST(i, >, guint32);
2369                         MINT_IN_BREAK;
2370                 MINT_IN_CASE(MINT_BGT_UN_I8)
2371                         BRELOP_CAST(l, >, guint64);
2372                         MINT_IN_BREAK;
2373                 MINT_IN_CASE(MINT_BGT_UN_R8)
2374                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
2375                         MINT_IN_BREAK;
2376                 MINT_IN_CASE(MINT_BLE_UN_I4_S)
2377                         BRELOP_S_CAST(i, <=, guint32);
2378                         MINT_IN_BREAK;
2379                 MINT_IN_CASE(MINT_BLE_UN_I8_S)
2380                         BRELOP_S_CAST(l, <=, guint64);
2381                         MINT_IN_BREAK;
2382                 MINT_IN_CASE(MINT_BLE_UN_R8_S)
2383                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2384                         MINT_IN_BREAK;
2385                 MINT_IN_CASE(MINT_BLE_UN_I4)
2386                         BRELOP_CAST(i, <=, guint32);
2387                         MINT_IN_BREAK;
2388                 MINT_IN_CASE(MINT_BLE_UN_I8)
2389                         BRELOP_CAST(l, <=, guint64);
2390                         MINT_IN_BREAK;
2391                 MINT_IN_CASE(MINT_BLE_UN_R8)
2392                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
2393                         MINT_IN_BREAK;
2394                 MINT_IN_CASE(MINT_BLT_UN_I4_S)
2395                         BRELOP_S_CAST(i, <, guint32);
2396                         MINT_IN_BREAK;
2397                 MINT_IN_CASE(MINT_BLT_UN_I8_S)
2398                         BRELOP_S_CAST(l, <, guint64);
2399                         MINT_IN_BREAK;
2400                 MINT_IN_CASE(MINT_BLT_UN_R8_S)
2401                         CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2402                         MINT_IN_BREAK;
2403                 MINT_IN_CASE(MINT_BLT_UN_I4)
2404                         BRELOP_CAST(i, <, guint32);
2405                         MINT_IN_BREAK;
2406                 MINT_IN_CASE(MINT_BLT_UN_I8)
2407                         BRELOP_CAST(l, <, guint64);
2408                         MINT_IN_BREAK;
2409                 MINT_IN_CASE(MINT_BLT_UN_R8)
2410                         CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
2411                         MINT_IN_BREAK;
2412                 MINT_IN_CASE(MINT_SWITCH) {
2413                         guint32 n;
2414                         const unsigned short *st;
2415                         ++ip;
2416                         n = READ32 (ip);
2417                         ip += 2;
2418                         st = ip + 2 * n;
2419                         --sp;
2420                         if ((guint32)sp->data.i < n) {
2421                                 gint offset;
2422                                 ip += 2 * (guint32)sp->data.i;
2423                                 offset = READ32 (ip);
2424                                 ip = st + offset;
2425                         } else {
2426                                 ip = st;
2427                         }
2428                         MINT_IN_BREAK;
2429                 }
2430                 MINT_IN_CASE(MINT_LDIND_I1)
2431                         ++ip;
2432                         sp[-1].data.i = *(gint8*)sp[-1].data.p;
2433                         MINT_IN_BREAK;
2434                 MINT_IN_CASE(MINT_LDIND_U1)
2435                         ++ip;
2436                         sp[-1].data.i = *(guint8*)sp[-1].data.p;
2437                         MINT_IN_BREAK;
2438                 MINT_IN_CASE(MINT_LDIND_I2)
2439                         ++ip;
2440                         sp[-1].data.i = *(gint16*)sp[-1].data.p;
2441                         MINT_IN_BREAK;
2442                 MINT_IN_CASE(MINT_LDIND_U2)
2443                         ++ip;
2444                         sp[-1].data.i = *(guint16*)sp[-1].data.p;
2445                         MINT_IN_BREAK;
2446                 MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
2447                 MINT_IN_CASE(MINT_LDIND_U4)
2448                         ++ip;
2449                         sp[-1].data.i = *(gint32*)sp[-1].data.p;
2450                         MINT_IN_BREAK;
2451                 MINT_IN_CASE(MINT_LDIND_I8)
2452                         ++ip;
2453                         sp[-1].data.l = *(gint64*)sp[-1].data.p;
2454                         MINT_IN_BREAK;
2455                 MINT_IN_CASE(MINT_LDIND_I) {
2456                         guint16 offset = * (guint16 *)(ip + 1);
2457                         sp[-1 - offset].data.p = *(gpointer*)sp[-1 - offset].data.p;
2458                         ip += 2;
2459                         MINT_IN_BREAK;
2460                 }
2461                 MINT_IN_CASE(MINT_LDIND_R4)
2462                         ++ip;
2463                         sp[-1].data.f = *(gfloat*)sp[-1].data.p;
2464                         MINT_IN_BREAK;
2465                 MINT_IN_CASE(MINT_LDIND_R8)
2466                         ++ip;
2467                         sp[-1].data.f = *(gdouble*)sp[-1].data.p;
2468                         MINT_IN_BREAK;
2469                 MINT_IN_CASE(MINT_LDIND_REF)
2470                         ++ip;
2471                         sp[-1].data.p = *(gpointer*)sp[-1].data.p;
2472                         MINT_IN_BREAK;
2473                 MINT_IN_CASE(MINT_STIND_REF) 
2474                         ++ip;
2475                         sp -= 2;
2476                         mono_gc_wbarrier_generic_store (sp->data.p, sp [1].data.p);
2477                         MINT_IN_BREAK;
2478                 MINT_IN_CASE(MINT_STIND_I1)
2479                         ++ip;
2480                         sp -= 2;
2481                         * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
2482                         MINT_IN_BREAK;
2483                 MINT_IN_CASE(MINT_STIND_I2)
2484                         ++ip;
2485                         sp -= 2;
2486                         * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
2487                         MINT_IN_BREAK;
2488                 MINT_IN_CASE(MINT_STIND_I4)
2489                         ++ip;
2490                         sp -= 2;
2491                         * (gint32 *) sp->data.p = sp[1].data.i;
2492                         MINT_IN_BREAK;
2493                 MINT_IN_CASE(MINT_STIND_I)
2494                         ++ip;
2495                         sp -= 2;
2496                         * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
2497                         MINT_IN_BREAK;
2498                 MINT_IN_CASE(MINT_STIND_I8)
2499                         ++ip;
2500                         sp -= 2;
2501                         * (gint64 *) sp->data.p = sp[1].data.l;
2502                         MINT_IN_BREAK;
2503                 MINT_IN_CASE(MINT_STIND_R4)
2504                         ++ip;
2505                         sp -= 2;
2506                         * (float *) sp->data.p = (gfloat)sp[1].data.f;
2507                         MINT_IN_BREAK;
2508                 MINT_IN_CASE(MINT_STIND_R8)
2509                         ++ip;
2510                         sp -= 2;
2511                         * (double *) sp->data.p = sp[1].data.f;
2512                         MINT_IN_BREAK;
2513 #define BINOP(datamem, op) \
2514         --sp; \
2515         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
2516         ++ip;
2517                 MINT_IN_CASE(MINT_ADD_I4)
2518                         BINOP(i, +);
2519                         MINT_IN_BREAK;
2520                 MINT_IN_CASE(MINT_ADD_I8)
2521                         BINOP(l, +);
2522                         MINT_IN_BREAK;
2523                 MINT_IN_CASE(MINT_ADD_R8)
2524                         BINOP(f, +);
2525                         MINT_IN_BREAK;
2526                 MINT_IN_CASE(MINT_ADD1_I4)
2527                         ++sp [-1].data.i;
2528                         ++ip;
2529                         MINT_IN_BREAK;
2530                 MINT_IN_CASE(MINT_SUB_I4)
2531                         BINOP(i, -);
2532                         MINT_IN_BREAK;
2533                 MINT_IN_CASE(MINT_SUB_I8)
2534                         BINOP(l, -);
2535                         MINT_IN_BREAK;
2536                 MINT_IN_CASE(MINT_SUB_R8)
2537                         BINOP(f, -);
2538                         MINT_IN_BREAK;
2539                 MINT_IN_CASE(MINT_SUB1_I4)
2540                         --sp [-1].data.i;
2541                         ++ip;
2542                         MINT_IN_BREAK;
2543                 MINT_IN_CASE(MINT_MUL_I4)
2544                         BINOP(i, *);
2545                         MINT_IN_BREAK;
2546                 MINT_IN_CASE(MINT_MUL_I8)
2547                         BINOP(l, *);
2548                         MINT_IN_BREAK;
2549                 MINT_IN_CASE(MINT_MUL_R8)
2550                         BINOP(f, *);
2551                         MINT_IN_BREAK;
2552                 MINT_IN_CASE(MINT_DIV_I4)
2553                         if (sp [-1].data.i == 0)
2554                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2555                         if (sp [-1].data.i == (-1))
2556                                 THROW_EX (mono_get_exception_overflow (), ip);
2557                         BINOP(i, /);
2558                         MINT_IN_BREAK;
2559                 MINT_IN_CASE(MINT_DIV_I8)
2560                         if (sp [-1].data.l == 0)
2561                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2562                         if (sp [-1].data.l == (-1))
2563                                 THROW_EX (mono_get_exception_overflow (), ip);
2564                         BINOP(l, /);
2565                         MINT_IN_BREAK;
2566                 MINT_IN_CASE(MINT_DIV_R8)
2567                         BINOP(f, /);
2568                         MINT_IN_BREAK;
2569
2570 #define BINOP_CAST(datamem, op, type) \
2571         --sp; \
2572         sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
2573         ++ip;
2574                 MINT_IN_CASE(MINT_DIV_UN_I4)
2575                         if (sp [-1].data.i == 0)
2576                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2577                         BINOP_CAST(i, /, guint32);
2578                         MINT_IN_BREAK;
2579                 MINT_IN_CASE(MINT_DIV_UN_I8)
2580                         if (sp [-1].data.l == 0)
2581                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2582                         BINOP_CAST(l, /, guint64);
2583                         MINT_IN_BREAK;
2584                 MINT_IN_CASE(MINT_REM_I4)
2585                         if (sp [-1].data.i == 0)
2586                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2587                         if (sp [-1].data.i == (-1))
2588                                 THROW_EX (mono_get_exception_overflow (), ip);
2589                         BINOP(i, %);
2590                         MINT_IN_BREAK;
2591                 MINT_IN_CASE(MINT_REM_I8)
2592                         if (sp [-1].data.l == 0)
2593                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2594                         if (sp [-1].data.l == (-1))
2595                                 THROW_EX (mono_get_exception_overflow (), ip);
2596                         BINOP(l, %);
2597                         MINT_IN_BREAK;
2598                 MINT_IN_CASE(MINT_REM_R8)
2599                         /* FIXME: what do we actually do here? */
2600                         --sp;
2601                         sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
2602                         ++ip;
2603                         MINT_IN_BREAK;
2604                 MINT_IN_CASE(MINT_REM_UN_I4)
2605                         if (sp [-1].data.i == 0)
2606                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2607                         BINOP_CAST(i, %, guint32);
2608                         MINT_IN_BREAK;
2609                 MINT_IN_CASE(MINT_REM_UN_I8)
2610                         if (sp [-1].data.l == 0)
2611                                 THROW_EX (mono_get_exception_divide_by_zero (), ip);
2612                         BINOP_CAST(l, %, guint64);
2613                         MINT_IN_BREAK;
2614                 MINT_IN_CASE(MINT_AND_I4)
2615                         BINOP(i, &);
2616                         MINT_IN_BREAK;
2617                 MINT_IN_CASE(MINT_AND_I8)
2618                         BINOP(l, &);
2619                         MINT_IN_BREAK;
2620                 MINT_IN_CASE(MINT_OR_I4)
2621                         BINOP(i, |);
2622                         MINT_IN_BREAK;
2623                 MINT_IN_CASE(MINT_OR_I8)
2624                         BINOP(l, |);
2625                         MINT_IN_BREAK;
2626                 MINT_IN_CASE(MINT_XOR_I4)
2627                         BINOP(i, ^);
2628                         MINT_IN_BREAK;
2629                 MINT_IN_CASE(MINT_XOR_I8)
2630                         BINOP(l, ^);
2631                         MINT_IN_BREAK;
2632
2633 #define SHIFTOP(datamem, op) \
2634         --sp; \
2635         sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
2636         ++ip;
2637
2638                 MINT_IN_CASE(MINT_SHL_I4)
2639                         SHIFTOP(i, <<);
2640                         MINT_IN_BREAK;
2641                 MINT_IN_CASE(MINT_SHL_I8)
2642                         SHIFTOP(l, <<);
2643                         MINT_IN_BREAK;
2644                 MINT_IN_CASE(MINT_SHR_I4)
2645                         SHIFTOP(i, >>);
2646                         MINT_IN_BREAK;
2647                 MINT_IN_CASE(MINT_SHR_I8)
2648                         SHIFTOP(l, >>);
2649                         MINT_IN_BREAK;
2650                 MINT_IN_CASE(MINT_SHR_UN_I4)
2651                         --sp;
2652                         sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
2653                         ++ip;
2654                         MINT_IN_BREAK;
2655                 MINT_IN_CASE(MINT_SHR_UN_I8)
2656                         --sp;
2657                         sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
2658                         ++ip;
2659                         MINT_IN_BREAK;
2660                 MINT_IN_CASE(MINT_NEG_I4)
2661                         sp [-1].data.i = - sp [-1].data.i;
2662                         ++ip;
2663                         MINT_IN_BREAK;
2664                 MINT_IN_CASE(MINT_NEG_I8)
2665                         sp [-1].data.l = - sp [-1].data.l;
2666                         ++ip;
2667                         MINT_IN_BREAK;
2668                 MINT_IN_CASE(MINT_NEG_R8)
2669                         sp [-1].data.f = - sp [-1].data.f;
2670                         ++ip;
2671                         MINT_IN_BREAK;
2672                 MINT_IN_CASE(MINT_NOT_I4)
2673                         sp [-1].data.i = ~ sp [-1].data.i;
2674                         ++ip;
2675                         MINT_IN_BREAK;
2676                 MINT_IN_CASE(MINT_NOT_I8)
2677                         sp [-1].data.l = ~ sp [-1].data.l;
2678                         ++ip;
2679                         MINT_IN_BREAK;
2680                 MINT_IN_CASE(MINT_CONV_I1_I4)
2681                         sp [-1].data.i = (gint8)sp [-1].data.i;
2682                         ++ip;
2683                         MINT_IN_BREAK;
2684                 MINT_IN_CASE(MINT_CONV_I1_I8)
2685                         sp [-1].data.i = (gint8)sp [-1].data.l;
2686                         ++ip;
2687                         MINT_IN_BREAK;
2688                 MINT_IN_CASE(MINT_CONV_I1_R8)
2689                         sp [-1].data.i = (gint8)sp [-1].data.f;
2690                         ++ip;
2691                         MINT_IN_BREAK;
2692                 MINT_IN_CASE(MINT_CONV_U1_I4)
2693                         sp [-1].data.i = (guint8)sp [-1].data.i;
2694                         ++ip;
2695                         MINT_IN_BREAK;
2696                 MINT_IN_CASE(MINT_CONV_U1_I8)
2697                         sp [-1].data.i = (guint8)sp [-1].data.l;
2698                         ++ip;
2699                         MINT_IN_BREAK;
2700                 MINT_IN_CASE(MINT_CONV_U1_R8)
2701                         sp [-1].data.i = (guint8)sp [-1].data.f;
2702                         ++ip;
2703                         MINT_IN_BREAK;
2704                 MINT_IN_CASE(MINT_CONV_I2_I4)
2705                         sp [-1].data.i = (gint16)sp [-1].data.i;
2706                         ++ip;
2707                         MINT_IN_BREAK;
2708                 MINT_IN_CASE(MINT_CONV_I2_I8)
2709                         sp [-1].data.i = (gint16)sp [-1].data.l;
2710                         ++ip;
2711                         MINT_IN_BREAK;
2712                 MINT_IN_CASE(MINT_CONV_I2_R8)
2713                         sp [-1].data.i = (gint16)sp [-1].data.f;
2714                         ++ip;
2715                         MINT_IN_BREAK;
2716                 MINT_IN_CASE(MINT_CONV_U2_I4)
2717                         sp [-1].data.i = (guint16)sp [-1].data.i;
2718                         ++ip;
2719                         MINT_IN_BREAK;
2720                 MINT_IN_CASE(MINT_CONV_U2_I8)
2721                         sp [-1].data.i = (guint16)sp [-1].data.l;
2722                         ++ip;
2723                         MINT_IN_BREAK;
2724                 MINT_IN_CASE(MINT_CONV_U2_R8)
2725                         sp [-1].data.i = (guint16)sp [-1].data.f;
2726                         ++ip;
2727                         MINT_IN_BREAK;
2728                 MINT_IN_CASE(MINT_CONV_I4_R8)
2729                         sp [-1].data.i = (gint32)sp [-1].data.f;
2730                         ++ip;
2731                         MINT_IN_BREAK;
2732                 MINT_IN_CASE(MINT_CONV_U4_I8)
2733                 MINT_IN_CASE(MINT_CONV_I4_I8)
2734                         sp [-1].data.i = (gint32)sp [-1].data.l;
2735                         ++ip;
2736                         MINT_IN_BREAK;
2737                 MINT_IN_CASE(MINT_CONV_I4_I8_SP)
2738                         sp [-2].data.i = (gint32)sp [-2].data.l;
2739                         ++ip;
2740                         MINT_IN_BREAK;
2741                 MINT_IN_CASE(MINT_CONV_U4_R8)
2742                         sp [-1].data.i = (guint32)sp [-1].data.f;
2743                         ++ip;
2744                         MINT_IN_BREAK;
2745                 MINT_IN_CASE(MINT_CONV_I8_I4)
2746                         sp [-1].data.l = sp [-1].data.i;
2747                         ++ip;
2748                         MINT_IN_BREAK;
2749                 MINT_IN_CASE(MINT_CONV_I8_I4_SP)
2750                         sp [-2].data.l = sp [-2].data.i;
2751                         ++ip;
2752                         MINT_IN_BREAK;
2753                 MINT_IN_CASE(MINT_CONV_I8_U4)
2754                         sp [-1].data.l = (guint32)sp [-1].data.i;
2755                         ++ip;
2756                         MINT_IN_BREAK;
2757                 MINT_IN_CASE(MINT_CONV_I8_R8)
2758                         sp [-1].data.l = (gint64)sp [-1].data.f;
2759                         ++ip;
2760                         MINT_IN_BREAK;
2761                 MINT_IN_CASE(MINT_CONV_R4_I4)
2762                         sp [-1].data.f = (float)sp [-1].data.i;
2763                         ++ip;
2764                         MINT_IN_BREAK;
2765                 MINT_IN_CASE(MINT_CONV_R4_I8)
2766                         sp [-1].data.f = (float)sp [-1].data.l;
2767                         ++ip;
2768                         MINT_IN_BREAK;
2769                 MINT_IN_CASE(MINT_CONV_R4_R8)
2770                         sp [-1].data.f = (float)sp [-1].data.f;
2771                         ++ip;
2772                         MINT_IN_BREAK;
2773                 MINT_IN_CASE(MINT_CONV_R8_I4)
2774                         sp [-1].data.f = (double)sp [-1].data.i;
2775                         ++ip;
2776                         MINT_IN_BREAK;
2777                 MINT_IN_CASE(MINT_CONV_R8_I8)
2778                         sp [-1].data.f = (double)sp [-1].data.l;
2779                         ++ip;
2780                         MINT_IN_BREAK;
2781                 MINT_IN_CASE(MINT_CONV_U8_I4)
2782                         sp [-1].data.l = sp [-1].data.i & 0xffffffff;
2783                         ++ip;
2784                         MINT_IN_BREAK;
2785                 MINT_IN_CASE(MINT_CONV_U8_R8)
2786                         sp [-1].data.l = (guint64)sp [-1].data.f;
2787                         ++ip;
2788                         MINT_IN_BREAK;
2789                 MINT_IN_CASE(MINT_CPOBJ) {
2790                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2791                         g_assert (c->byval_arg.type == MONO_TYPE_VALUETYPE);
2792                         /* if this assertion fails, we need to add a write barrier */
2793                         g_assert (!MONO_TYPE_IS_REFERENCE (&c->byval_arg));
2794                         stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
2795                         ip += 2;
2796                         sp -= 2;
2797                         MINT_IN_BREAK;
2798                 }
2799                 MINT_IN_CASE(MINT_LDOBJ) {
2800                         void *p;
2801                         c = rtm->data_items[* (guint16 *)(ip + 1)];
2802                         ip += 2;
2803                         p = sp [-1].data.p;
2804                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
2805                                 int size = mono_class_value_size (c, NULL);
2806                                 sp [-1].data.p = vt_sp;
2807                                 vt_sp += (size + 7) & ~7;
2808                         }
2809                         stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
2810                         MINT_IN_BREAK;
2811                 }
2812                 MINT_IN_CASE(MINT_LDSTR)
2813                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
2814                         ++sp;
2815                         ip += 2;
2816                         MINT_IN_BREAK;
2817                 MINT_IN_CASE(MINT_NEWOBJ) {
2818                         MonoClass *newobj_class;
2819                         MonoMethodSignature *csig;
2820                         stackval valuetype_this;
2821                         guint32 token;
2822                         stackval retval;
2823
2824                         frame->ip = ip;
2825
2826                         token = * (guint16 *)(ip + 1);
2827                         ip += 2;
2828
2829                         child_frame.ip = NULL;
2830                         child_frame.ex = NULL;
2831
2832                         child_frame.runtime_method = rtm->data_items [token];
2833                         csig = mono_method_signature (child_frame.runtime_method->method);
2834                         newobj_class = child_frame.runtime_method->method->klass;
2835                         /*if (profiling_classes) {
2836                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
2837                                 count++;
2838                                 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
2839                         }*/
2840
2841                         if (newobj_class->parent == mono_defaults.array_class) {
2842                                 sp -= csig->param_count;
2843                                 child_frame.stack_args = sp;
2844                                 o = ves_array_create (&child_frame, context->domain, newobj_class, csig, sp);
2845                                 if (child_frame.ex)
2846                                         THROW_EX (child_frame.ex, ip);
2847                                 goto array_constructed;
2848                         }
2849
2850                         g_assert (csig->hasthis);
2851                         if (csig->param_count) {
2852                                 sp -= csig->param_count;
2853                                 memmove (sp + 1, sp, csig->param_count * sizeof (stackval));
2854                         }
2855                         child_frame.stack_args = sp;
2856
2857                         /*
2858                          * First arg is the object.
2859                          */
2860                         if (newobj_class->valuetype) {
2861                                 MonoType *t = &newobj_class->byval_arg;
2862                                 memset (&valuetype_this, 0, sizeof (stackval));
2863                                 if (!newobj_class->enumtype && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
2864                                         sp->data.p = vt_sp;
2865                                         valuetype_this.data.p = vt_sp;
2866                                 } else {
2867                                         sp->data.p = &valuetype_this;
2868                                 }
2869                         } else {
2870                                 if (newobj_class != mono_defaults.string_class) {
2871                                         context->managed_code = 0;
2872                                         o = mono_object_new_checked (context->domain, newobj_class, &error);
2873                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2874                                         context->managed_code = 1;
2875                                         if (*mono_thread_interruption_request_flag ())
2876                                                 mono_thread_interruption_checkpoint ();
2877                                         sp->data.p = o;
2878                                 } else {
2879                                         sp->data.p = NULL;
2880                                         child_frame.retval = &retval;
2881                                 }
2882                         }
2883
2884                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2885
2886                         ves_exec_method_with_context (&child_frame, context);
2887
2888                         context->current_frame = frame;
2889
2890                         if (child_frame.ex) {
2891                                 /*
2892                                  * An exception occurred, need to run finally, fault and catch handlers..
2893                                  */
2894                                 frame->ex = child_frame.ex;
2895                                 goto handle_finally;
2896                         }
2897                         /*
2898                          * a constructor returns void, but we need to return the object we created
2899                          */
2900 array_constructed:
2901                         if (newobj_class->valuetype && !newobj_class->enumtype) {
2902                                 *sp = valuetype_this;
2903                         } else if (newobj_class == mono_defaults.string_class) {
2904                                 *sp = retval;
2905                         } else {
2906                                 sp->data.p = o;
2907                         }
2908                         ++sp;
2909                         MINT_IN_BREAK;
2910                 }
2911                 MINT_IN_CASE(MINT_CASTCLASS)
2912                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2913                         if ((o = sp [-1].data.p)) {
2914                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
2915                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2916                                 if (!isinst_obj)
2917                                         THROW_EX (mono_get_exception_invalid_cast (), ip);
2918                         }
2919                         ip += 2;
2920                         MINT_IN_BREAK;
2921                 MINT_IN_CASE(MINT_ISINST)
2922                         c = rtm->data_items [*(guint16 *)(ip + 1)];
2923                         if ((o = sp [-1].data.p)) {
2924                                 MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
2925                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2926                                 if (!isinst_obj)
2927                                         sp [-1].data.p = NULL;
2928                         }
2929                         ip += 2;
2930                         MINT_IN_BREAK;
2931                 MINT_IN_CASE(MINT_CONV_R_UN_I4)
2932                         sp [-1].data.f = (double)(guint32)sp [-1].data.i;
2933                         ++ip;
2934                         MINT_IN_BREAK;
2935                 MINT_IN_CASE(MINT_CONV_R_UN_I8)
2936                         sp [-1].data.f = (double)(guint64)sp [-1].data.l;
2937                         ++ip;
2938                         MINT_IN_BREAK;
2939                 MINT_IN_CASE(MINT_UNBOX)
2940                         c = rtm->data_items[*(guint16 *)(ip + 1)];
2941                         
2942                         o = sp [-1].data.p;
2943                         if (!o)
2944                                 THROW_EX (mono_get_exception_null_reference (), ip);
2945
2946                         MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
2947                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2948                         if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
2949                                 THROW_EX (mono_get_exception_invalid_cast (), ip);
2950
2951                         sp [-1].data.p = mono_object_unbox (o);
2952                         ip += 2;
2953                         MINT_IN_BREAK;
2954                 MINT_IN_CASE(MINT_THROW)
2955                         --sp;
2956                         frame->ex_handler = NULL;
2957                         if (!sp->data.p)
2958                                 sp->data.p = mono_get_exception_null_reference ();
2959                         THROW_EX ((MonoException *)sp->data.p, ip);
2960                         MINT_IN_BREAK;
2961                 MINT_IN_CASE(MINT_LDFLDA_UNSAFE)
2962                         o = sp [-1].data.p;
2963                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
2964                         ip += 2;
2965                         MINT_IN_BREAK;
2966                 MINT_IN_CASE(MINT_LDFLDA)
2967                         o = sp [-1].data.p;
2968                         if (!o)
2969                                 THROW_EX (mono_get_exception_null_reference (), ip);
2970                         sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
2971                         ip += 2;
2972                         MINT_IN_BREAK;
2973                 MINT_IN_CASE(MINT_CKNULL)
2974                         o = sp [-1].data.p;
2975                         if (!o)
2976                                 THROW_EX (mono_get_exception_null_reference (), ip);
2977                         ++ip;
2978                         MINT_IN_BREAK;
2979
2980 #define LDFLD(datamem, fieldtype) \
2981         o = sp [-1].data.p; \
2982         if (!o) \
2983                 THROW_EX (mono_get_exception_null_reference (), ip); \
2984         sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
2985         ip += 2;
2986
2987                 MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
2988                 MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
2989                 MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
2990                 MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
2991                 MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
2992                 MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
2993                 MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
2994                 MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
2995                 MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
2996                 MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
2997
2998                 MINT_IN_CASE(MINT_LDFLD_VT)
2999                         o = sp [-1].data.p;
3000                         if (!o)
3001                                 THROW_EX (mono_get_exception_null_reference (), ip);
3002                         i32 = READ32(ip + 2);
3003                         sp [-1].data.p = vt_sp;
3004                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3005                         vt_sp += (i32 + 7) & ~7;
3006                         ip += 4;
3007                         MINT_IN_BREAK;
3008
3009                 MINT_IN_CASE(MINT_LDRMFLD) {
3010                         gpointer tmp;
3011                         MonoClassField *field;
3012                         char *addr;
3013
3014                         o = sp [-1].data.p;
3015                         if (!o)
3016                                 THROW_EX (mono_get_exception_null_reference (), ip);
3017                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3018                         ip += 2;
3019                         if (mono_object_is_transparent_proxy (o)) {
3020                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3021
3022                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3023                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3024                         } else {
3025                                 addr = (char*)o + field->offset;
3026                         }                               
3027
3028                         stackval_from_data (field->type, &sp [-1], addr, FALSE);
3029                         MINT_IN_BREAK;
3030                 }
3031
3032                 MINT_IN_CASE(MINT_LDRMFLD_VT) {
3033                         MonoClassField *field;
3034                         char *addr;
3035                         gpointer tmp;
3036
3037                         o = sp [-1].data.p;
3038                         if (!o)
3039                                 THROW_EX (mono_get_exception_null_reference (), ip);
3040                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3041                         i32 = READ32(ip + 2);
3042                         ip += 4;
3043                         if (mono_object_is_transparent_proxy (o)) {
3044                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3045                                 addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
3046                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3047                         } else {
3048                                 addr = (char*)o + field->offset;
3049                         }                               
3050
3051                         sp [-1].data.p = vt_sp;
3052                         memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
3053                         vt_sp += (i32 + 7) & ~7;
3054                         memcpy(sp [-1].data.p, addr, i32);
3055                         MINT_IN_BREAK;
3056                 }
3057
3058 #define STFLD(datamem, fieldtype) \
3059         o = sp [-2].data.p; \
3060         if (!o) \
3061                 THROW_EX (mono_get_exception_null_reference (), ip); \
3062         sp -= 2; \
3063         * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
3064         ip += 2;
3065
3066                 MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
3067                 MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
3068                 MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
3069                 MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
3070                 MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
3071                 MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
3072                 MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
3073                 MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
3074                 MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
3075                 MINT_IN_CASE(MINT_STFLD_O)
3076                         o = sp [-2].data.p;
3077                         if (!o)
3078                                 THROW_EX (mono_get_exception_null_reference (), ip);
3079                         sp -= 2;
3080                         mono_gc_wbarrier_set_field (o, (char *) o + * (guint16 *)(ip + 1), sp [1].data.p);
3081                         ip += 2;
3082                         MINT_IN_BREAK;
3083
3084                 MINT_IN_CASE(MINT_STFLD_VT)
3085                         o = sp [-2].data.p;
3086                         if (!o)
3087                                 THROW_EX (mono_get_exception_null_reference (), ip);
3088                         i32 = READ32(ip + 2);
3089                         sp -= 2;
3090                         memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
3091                         vt_sp -= (i32 + 7) & ~7;
3092                         ip += 4;
3093                         MINT_IN_BREAK;
3094
3095                 MINT_IN_CASE(MINT_STRMFLD) {
3096                         MonoClassField *field;
3097
3098                         o = sp [-2].data.p;
3099                         if (!o)
3100                                 THROW_EX (mono_get_exception_null_reference (), ip);
3101                         
3102                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3103                         ip += 2;
3104
3105                         if (mono_object_is_transparent_proxy (o)) {
3106                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3107                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3108                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3109                         } else
3110                                 stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
3111
3112                         sp -= 2;
3113                         MINT_IN_BREAK;
3114                 }
3115                 MINT_IN_CASE(MINT_STRMFLD_VT) {
3116                         MonoClassField *field;
3117
3118                         o = sp [-2].data.p;
3119                         if (!o)
3120                                 THROW_EX (mono_get_exception_null_reference (), ip);
3121                         field = rtm->data_items[* (guint16 *)(ip + 1)];
3122                         i32 = READ32(ip + 2);
3123                         ip += 4;
3124
3125                         if (mono_object_is_transparent_proxy (o)) {
3126                                 MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
3127                                 mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
3128                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3129                         } else
3130                                 memcpy((char*)o + field->offset, sp [-1].data.p, i32);
3131
3132                         sp -= 2;
3133                         vt_sp -= (i32 + 7) & ~7;
3134                         MINT_IN_BREAK;
3135                 }
3136                 MINT_IN_CASE(MINT_LDSFLDA) {
3137                         MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
3138                         sp->data.p = mono_class_static_field_address (context->domain, field);
3139                         ip += 2;
3140                         ++sp;
3141                         MINT_IN_BREAK;
3142                 }
3143                 MINT_IN_CASE(MINT_LDSFLD) {
3144                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3145                         gpointer addr = mono_class_static_field_address (context->domain, field);
3146                         stackval_from_data (field->type, sp, addr, FALSE);
3147                         ip += 2;
3148                         ++sp;
3149                         MINT_IN_BREAK;
3150                 }
3151                 MINT_IN_CASE(MINT_LDSFLD_VT) {
3152                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3153                         gpointer addr = mono_class_static_field_address (context->domain, field);
3154                         int size = READ32 (ip + 2);
3155                         ip += 4;
3156
3157                         sp->data.p = vt_sp;
3158                         vt_sp += (size + 7) & ~7;
3159                         stackval_from_data (field->type, sp, addr, FALSE);
3160                         ++sp;
3161                         MINT_IN_BREAK;
3162                 }
3163                 MINT_IN_CASE(MINT_STSFLD) {
3164                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3165                         gpointer addr = mono_class_static_field_address (context->domain, field);
3166                         ip += 2;
3167                         --sp;
3168                         stackval_to_data (field->type, sp, addr, FALSE);
3169                         MINT_IN_BREAK;
3170                 }
3171                 MINT_IN_CASE(MINT_STSFLD_VT) {
3172                         MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
3173                         gpointer addr = mono_class_static_field_address (context->domain, field);
3174                         int size = READ32 (ip + 2);
3175                         ip += 4;
3176
3177                         --sp;
3178                         stackval_to_data (field->type, sp, addr, FALSE);
3179                         vt_sp -= (size + 7) & ~7;
3180                         MINT_IN_BREAK;
3181                 }
3182                 MINT_IN_CASE(MINT_STOBJ_VT) {
3183                         int size;
3184                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3185                         ip += 2;
3186                         size = mono_class_value_size (c, NULL);
3187                         memcpy(sp [-2].data.p, sp [-1].data.p, size);
3188                         vt_sp -= (size + 7) & ~7;
3189                         sp -= 2;
3190                         MINT_IN_BREAK;
3191                 }
3192                 MINT_IN_CASE(MINT_STOBJ) {
3193                         c = rtm->data_items[* (guint16 *)(ip + 1)];
3194                         ip += 2;
3195
3196                         g_assert (!c->byval_arg.byref);
3197                         if (MONO_TYPE_IS_REFERENCE (&c->byval_arg))
3198                                 mono_gc_wbarrier_generic_store (sp [-2].data.p, sp [-1].data.p);
3199                         else
3200                                 stackval_from_data (&c->byval_arg, sp [-2].data.p, (char *) &sp [-1].data.p, FALSE);
3201                         sp -= 2;
3202                         MINT_IN_BREAK;
3203                 }
3204                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
3205                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3206                                 THROW_EX (mono_get_exception_overflow (), ip);
3207                         sp [-1].data.i = (guint32)sp [-1].data.f;
3208                         ++ip;
3209                         MINT_IN_BREAK;
3210                 MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
3211                         if (sp [-1].data.i < 0)
3212                                 THROW_EX (mono_get_exception_overflow (), ip);
3213                         sp [-1].data.l = sp [-1].data.i;
3214                         ++ip;
3215                         MINT_IN_BREAK;
3216                 MINT_IN_CASE(MINT_CONV_OVF_U8_I8)
3217                         if (sp [-1].data.l < 0)
3218                                 THROW_EX (mono_get_exception_overflow (), ip);
3219                         ++ip;
3220                         MINT_IN_BREAK;
3221                 MINT_IN_CASE(MINT_CONV_OVF_I8_U8)
3222                         if ((guint64) sp [-1].data.l > MYGINT64_MAX)
3223                                 THROW_EX (mono_get_exception_overflow (), ip);
3224                         ++ip;
3225                         MINT_IN_BREAK;
3226                 MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
3227                 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
3228                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGINT64_MAX)
3229                                 THROW_EX (mono_get_exception_overflow (), ip);
3230                         sp [-1].data.l = (guint64)sp [-1].data.f;
3231                         ++ip;
3232                         MINT_IN_BREAK;
3233                 MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
3234                         if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
3235                                 THROW_EX (mono_get_exception_overflow (), ip);
3236                         sp [-1].data.l = (gint64)sp [-1].data.f;
3237                         ++ip;
3238                         MINT_IN_BREAK;
3239                 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
3240                         if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
3241                                 THROW_EX (mono_get_exception_overflow (), ip);
3242                         sp [-1].data.i = (mono_u)sp [-1].data.l;
3243                         ++ip;
3244                         MINT_IN_BREAK;
3245                 MINT_IN_CASE(MINT_BOX) {
3246                         c = rtm->data_items [* (guint16 *)(ip + 1)];
3247                         guint16 offset = * (guint16 *)(ip + 2);
3248
3249                         if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
3250                                 int size = mono_class_value_size (c, NULL);
3251                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
3252                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3253                                 size = (size + 7) & ~7;
3254                                 vt_sp -= size;
3255                         } else {
3256                                 stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
3257                                 sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
3258                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3259                         }
3260                         ip += 3;
3261                         MINT_IN_BREAK;
3262                 }
3263                 MINT_IN_CASE(MINT_NEWARR)
3264                         sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
3265                         if (!mono_error_ok (&error)) {
3266                                 THROW_EX (mono_error_convert_to_exception (&error), ip);
3267                         }
3268                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3269                         ip += 2;
3270                         /*if (profiling_classes) {
3271                                 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3272                                 count++;
3273                                 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3274                         }*/
3275
3276                         MINT_IN_BREAK;
3277                 MINT_IN_CASE(MINT_LDLEN)
3278                         o = sp [-1].data.p;
3279                         if (!o)
3280                                 THROW_EX (mono_get_exception_null_reference (), ip);
3281                         sp [-1].data.nati = mono_array_length ((MonoArray *)o);
3282                         ++ip;
3283                         MINT_IN_BREAK;
3284                 MINT_IN_CASE(MINT_GETCHR) {
3285                         MonoString *s;
3286                         s = sp [-2].data.p;
3287                         if (!s)
3288                                 THROW_EX (mono_get_exception_null_reference (), ip);
3289                         i32 = sp [-1].data.i;
3290                         if (i32 < 0 || i32 >= mono_string_length (s))
3291                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3292                         --sp;
3293                         sp [-1].data.i = mono_string_chars(s)[i32];
3294                         ++ip;
3295                         MINT_IN_BREAK;
3296                 }
3297                 MINT_IN_CASE(MINT_STRLEN)
3298                         ++ip;
3299                         o = sp [-1].data.p;
3300                         if (!o)
3301                                 THROW_EX (mono_get_exception_null_reference (), ip);
3302                         sp [-1].data.i = mono_string_length ((MonoString*) o);
3303                         MINT_IN_BREAK;
3304                 MINT_IN_CASE(MINT_ARRAY_RANK)
3305                         o = sp [-1].data.p;
3306                         if (!o)
3307                                 THROW_EX (mono_get_exception_null_reference (), ip);
3308                         sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
3309                         ip++;
3310                         MINT_IN_BREAK;
3311                 MINT_IN_CASE(MINT_LDELEMA)
3312                 MINT_IN_CASE(MINT_LDELEMA_TC) {
3313                         gboolean needs_typecheck = *ip == MINT_LDELEMA_TC;
3314                         
3315                         MonoClass *klass = rtm->data_items [*(guint16 *) (ip + 1)];
3316                         guint16 numargs = *(guint16 *) (ip + 2);
3317                         ip += 3;
3318                         sp -= numargs;
3319
3320                         o = sp [0].data.p;
3321                         sp->data.p = ves_array_element_address (frame, klass, (MonoArray *) o, &sp [1], needs_typecheck);
3322                         if (frame->ex)
3323                                 THROW_EX (frame->ex, ip);
3324                         ++sp;
3325
3326                         MINT_IN_BREAK;
3327                 }
3328                 MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
3329                 MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
3330                 MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
3331                 MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
3332                 MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
3333                 MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
3334                 MINT_IN_CASE(MINT_LDELEM_I8)  /* fall through */
3335                 MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
3336                 MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
3337                 MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
3338                 MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
3339                 MINT_IN_CASE(MINT_LDELEM_VT) {
3340                         MonoArray *o;
3341                         mono_u aindex;
3342
3343                         sp -= 2;
3344
3345                         o = sp [0].data.p;
3346                         if (!o)
3347                                 THROW_EX (mono_get_exception_null_reference (), ip);
3348
3349                         aindex = sp [1].data.i;
3350                         if (aindex >= mono_array_length (o))
3351                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3352
3353                         /*
3354                          * FIXME: throw mono_get_exception_array_type_mismatch () if needed 
3355                          */
3356                         switch (*ip) {
3357                         case MINT_LDELEM_I1:
3358                                 sp [0].data.i = mono_array_get (o, gint8, aindex);
3359                                 break;
3360                         case MINT_LDELEM_U1:
3361                                 sp [0].data.i = mono_array_get (o, guint8, aindex);
3362                                 break;
3363                         case MINT_LDELEM_I2:
3364                                 sp [0].data.i = mono_array_get (o, gint16, aindex);
3365                                 break;
3366                         case MINT_LDELEM_U2:
3367                                 sp [0].data.i = mono_array_get (o, guint16, aindex);
3368                                 break;
3369                         case MINT_LDELEM_I:
3370                                 sp [0].data.nati = mono_array_get (o, mono_i, aindex);
3371                                 break;
3372                         case MINT_LDELEM_I4:
3373                                 sp [0].data.i = mono_array_get (o, gint32, aindex);
3374                                 break;
3375                         case MINT_LDELEM_U4:
3376                                 sp [0].data.i = mono_array_get (o, guint32, aindex);
3377                                 break;
3378                         case MINT_LDELEM_I8:
3379                                 sp [0].data.l = mono_array_get (o, guint64, aindex);
3380                                 break;
3381                         case MINT_LDELEM_R4:
3382                                 sp [0].data.f = mono_array_get (o, float, aindex);
3383                                 break;
3384                         case MINT_LDELEM_R8:
3385                                 sp [0].data.f = mono_array_get (o, double, aindex);
3386                                 break;
3387                         case MINT_LDELEM_REF:
3388                                 sp [0].data.p = mono_array_get (o, gpointer, aindex);
3389                                 break;
3390                         case MINT_LDELEM_VT: {
3391                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
3392                                 i32 = READ32 (ip + 2);
3393                                 char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
3394                                 sp [0].data.vt = vt_sp;
3395                                 stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
3396                                 vt_sp += (i32 + 7) & ~7;
3397                                 ip += 3;
3398                                 break;
3399                         }
3400                         default:
3401                                 ves_abort();
3402                         }
3403
3404                         ++ip;
3405                         ++sp;
3406                         MINT_IN_BREAK;
3407                 }
3408                 MINT_IN_CASE(MINT_STELEM_I)  /* fall through */
3409                 MINT_IN_CASE(MINT_STELEM_I1) /* fall through */ 
3410                 MINT_IN_CASE(MINT_STELEM_U1) /* fall through */
3411                 MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
3412                 MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
3413                 MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
3414                 MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
3415                 MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
3416                 MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
3417                 MINT_IN_CASE(MINT_STELEM_VT) {
3418                         mono_u aindex;
3419
3420                         sp -= 3;
3421
3422                         o = sp [0].data.p;
3423                         if (!o)
3424                                 THROW_EX (mono_get_exception_null_reference (), ip);
3425
3426                         aindex = sp [1].data.i;
3427                         if (aindex >= mono_array_length ((MonoArray *)o))
3428                                 THROW_EX (mono_get_exception_index_out_of_range (), ip);
3429
3430                         switch (*ip) {
3431                         case MINT_STELEM_I:
3432                                 mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
3433                                 break;
3434                         case MINT_STELEM_I1:
3435                                 mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
3436                                 break;
3437                         case MINT_STELEM_U1:
3438                                 mono_array_set ((MonoArray *) o, guint8, aindex, sp [2].data.i);
3439                                 break;
3440                         case MINT_STELEM_I2:
3441                                 mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
3442                                 break;
3443                         case MINT_STELEM_I4:
3444                                 mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
3445                                 break;
3446                         case MINT_STELEM_I8:
3447                                 mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
3448                                 break;
3449                         case MINT_STELEM_R4:
3450                                 mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
3451                                 break;
3452                         case MINT_STELEM_R8:
3453                                 mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
3454                                 break;
3455                         case MINT_STELEM_REF: {
3456                                 MonoObject *isinst_obj = mono_object_isinst_checked (sp [2].data.p, mono_object_class (o)->element_class, &error);
3457                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3458                                 if (sp [2].data.p && !isinst_obj)
3459                                         THROW_EX (mono_get_exception_array_type_mismatch (), ip);
3460                                 mono_array_setref ((MonoArray *) o, aindex, sp [2].data.p);
3461                                 break;
3462                         }
3463                         case MINT_STELEM_VT: {
3464                                 MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
3465                                 i32 = READ32 (ip + 2);
3466                                 char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
3467
3468                                 stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
3469                                 vt_sp -= (i32 + 7) & ~7;
3470                                 ip += 3;
3471                                 break;
3472                         }
3473                         default:
3474                                 ves_abort();
3475                         }
3476
3477                         ++ip;
3478                         MINT_IN_BREAK;
3479                 }
3480                 MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
3481                         if (sp [-1].data.i < 0)
3482                                 THROW_EX (mono_get_exception_overflow (), ip);
3483                         ++ip;
3484                         MINT_IN_BREAK;
3485                 MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
3486                         if (sp [-1].data.l < MYGINT32_MIN || 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_U8)
3492                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGINT32_MAX)
3493                                 THROW_EX (mono_get_exception_overflow (), ip);
3494                         sp [-1].data.i = (gint32) sp [-1].data.l;
3495                         ++ip;
3496                         MINT_IN_BREAK;
3497                 MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
3498                         if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
3499                                 THROW_EX (mono_get_exception_overflow (), ip);
3500                         sp [-1].data.i = (gint32) sp [-1].data.f;
3501                         ++ip;
3502                         MINT_IN_BREAK;
3503                 MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
3504                         if (sp [-1].data.i < 0)
3505                                 THROW_EX (mono_get_exception_overflow (), ip);
3506                         ++ip;
3507                         MINT_IN_BREAK;
3508                 MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
3509                         if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
3510                                 THROW_EX (mono_get_exception_overflow (), ip);
3511                         sp [-1].data.i = (guint32) sp [-1].data.l;
3512                         ++ip;
3513                         MINT_IN_BREAK;
3514                 MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
3515                         if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
3516                                 THROW_EX (mono_get_exception_overflow (), ip);
3517                         sp [-1].data.i = (guint32) sp [-1].data.f;
3518                         ++ip;
3519                         MINT_IN_BREAK;
3520                 MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
3521                         if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
3522                                 THROW_EX (mono_get_exception_overflow (), ip);
3523                         ++ip;
3524                         MINT_IN_BREAK;
3525                 MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
3526                         if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
3527                                 THROW_EX (mono_get_exception_overflow (), ip);
3528                         sp [-1].data.i = (gint16) sp [-1].data.l;
3529                         ++ip;
3530                         MINT_IN_BREAK;
3531                 MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
3532                         if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
3533                                 THROW_EX (mono_get_exception_overflow (), ip);
3534                         sp [-1].data.i = (gint16) sp [-1].data.f;
3535                         ++ip;
3536                         MINT_IN_BREAK;
3537                 MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
3538                         if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
3539                                 THROW_EX (mono_get_exception_overflow (), ip);
3540                         ++ip;
3541                         MINT_IN_BREAK;
3542                 MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
3543                         if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
3544                                 THROW_EX (mono_get_exception_overflow (), ip);
3545                         sp [-1].data.i = (guint16) sp [-1].data.l;
3546                         ++ip;
3547                         MINT_IN_BREAK;
3548                 MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
3549                         if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
3550                                 THROW_EX (mono_get_exception_overflow (), ip);
3551                         sp [-1].data.i = (guint16) sp [-1].data.f;
3552                         ++ip;
3553                         MINT_IN_BREAK;
3554                 MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
3555                         if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
3556                                 THROW_EX (mono_get_exception_overflow (), ip);
3557                         ++ip;
3558                         MINT_IN_BREAK;
3559                 MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
3560                         if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
3561                                 THROW_EX (mono_get_exception_overflow (), ip);
3562                         sp [-1].data.i = (gint8) sp [-1].data.l;
3563                         ++ip;
3564                         MINT_IN_BREAK;
3565                 MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
3566                         if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
3567                                 THROW_EX (mono_get_exception_overflow (), ip);
3568                         sp [-1].data.i = (gint8) sp [-1].data.f;
3569                         ++ip;
3570                         MINT_IN_BREAK;
3571                 MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
3572                         if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
3573                                 THROW_EX (mono_get_exception_overflow (), ip);
3574                         ++ip;
3575                         MINT_IN_BREAK;
3576                 MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
3577                         if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
3578                                 THROW_EX (mono_get_exception_overflow (), ip);
3579                         sp [-1].data.i = (guint8) sp [-1].data.l;
3580                         ++ip;
3581                         MINT_IN_BREAK;
3582                 MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
3583                         if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
3584                                 THROW_EX (mono_get_exception_overflow (), ip);
3585                         sp [-1].data.i = (guint8) sp [-1].data.f;
3586                         ++ip;
3587                         MINT_IN_BREAK;
3588 #if 0
3589                 MINT_IN_CASE(MINT_LDELEM) 
3590                 MINT_IN_CASE(MINT_STELEM) 
3591                 MINT_IN_CASE(MINT_UNBOX_ANY) 
3592
3593                 MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
3594 #endif
3595                 MINT_IN_CASE(MINT_CKFINITE)
3596                         if (!isfinite(sp [-1].data.f))
3597                                 THROW_EX (mono_get_exception_arithmetic (), ip);
3598                         ++ip;
3599                         MINT_IN_BREAK;
3600 #if 0
3601                 MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
3602 #endif
3603                 MINT_IN_CASE(MINT_LDTOKEN)
3604                         sp->data.p = vt_sp;
3605                         vt_sp += 8;
3606                         * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
3607                         ip += 2;
3608                         ++sp;
3609                         MINT_IN_BREAK;
3610                 MINT_IN_CASE(MINT_ADD_OVF_I4)
3611                         if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3612                                 THROW_EX (mono_get_exception_overflow (), ip);
3613                         BINOP(i, +);
3614                         MINT_IN_BREAK;
3615                 MINT_IN_CASE(MINT_ADD_OVF_I8)
3616                         if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3617                                 THROW_EX (mono_get_exception_overflow (), ip);
3618                         BINOP(l, +);
3619                         MINT_IN_BREAK;
3620                 MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
3621                         if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3622                                 THROW_EX (mono_get_exception_overflow (), ip);
3623                         BINOP_CAST(i, +, guint32);
3624                         MINT_IN_BREAK;
3625                 MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
3626                         if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3627                                 THROW_EX (mono_get_exception_overflow (), ip);
3628                         BINOP_CAST(l, +, guint64);
3629                         MINT_IN_BREAK;
3630                 MINT_IN_CASE(MINT_MUL_OVF_I4)
3631                         if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3632                                 THROW_EX (mono_get_exception_overflow (), ip);
3633                         BINOP(i, *);
3634                         MINT_IN_BREAK;
3635                 MINT_IN_CASE(MINT_MUL_OVF_I8)
3636                         if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3637                                 THROW_EX (mono_get_exception_overflow (), ip);
3638                         BINOP(l, *);
3639                         MINT_IN_BREAK;
3640                 MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
3641                         if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3642                                 THROW_EX (mono_get_exception_overflow (), ip);
3643                         BINOP_CAST(i, *, guint32);
3644                         MINT_IN_BREAK;
3645                 MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
3646                         if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3647                                 THROW_EX (mono_get_exception_overflow (), ip);
3648                         BINOP_CAST(l, *, guint64);
3649                         MINT_IN_BREAK;
3650                 MINT_IN_CASE(MINT_SUB_OVF_I4)
3651                         if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
3652                                 THROW_EX (mono_get_exception_overflow (), ip);
3653                         BINOP(i, -);
3654                         MINT_IN_BREAK;
3655                 MINT_IN_CASE(MINT_SUB_OVF_I8)
3656                         if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
3657                                 THROW_EX (mono_get_exception_overflow (), ip);
3658                         BINOP(l, -);
3659                         MINT_IN_BREAK;
3660                 MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
3661                         if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
3662                                 THROW_EX (mono_get_exception_overflow (), ip);
3663                         BINOP_CAST(i, -, guint32);
3664                         MINT_IN_BREAK;
3665                 MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
3666                         if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
3667                                 THROW_EX (mono_get_exception_overflow (), ip);
3668                         BINOP_CAST(l, -, guint64);
3669                         MINT_IN_BREAK;
3670                 MINT_IN_CASE(MINT_ENDFINALLY)
3671                         if (finally_ips) {
3672                                 ip = finally_ips->data;
3673                                 finally_ips = g_slist_remove (finally_ips, ip);
3674                                 goto main_loop;
3675                         }
3676                         if (frame->ex)
3677                                 goto handle_fault;
3678                         ves_abort();
3679                         MINT_IN_BREAK;
3680                 MINT_IN_CASE(MINT_LEAVE) /* Fall through */
3681                 MINT_IN_CASE(MINT_LEAVE_S)
3682                         while (sp > frame->stack) {
3683                                 --sp;
3684                         }
3685                         frame->ip = ip;
3686                         if (*ip == MINT_LEAVE_S) {
3687                                 ip += (short) *(ip + 1);
3688                         } else {
3689                                 ip += (gint32) READ32 (ip + 1);
3690                         }
3691                         endfinally_ip = ip;
3692                         if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
3693                                 frame->ex_handler = NULL;
3694                                 frame->ex = NULL;
3695                         }
3696                         goto handle_finally;
3697                         MINT_IN_BREAK;
3698                 MINT_IN_CASE(MINT_ICALL_V_V) 
3699                 MINT_IN_CASE(MINT_ICALL_V_P)
3700                 MINT_IN_CASE(MINT_ICALL_P_V) 
3701                 MINT_IN_CASE(MINT_ICALL_P_P)
3702                 MINT_IN_CASE(MINT_ICALL_PP_V)
3703                 MINT_IN_CASE(MINT_ICALL_PI_V)
3704                 MINT_IN_CASE(MINT_ICALL_PP_P)
3705                 MINT_IN_CASE(MINT_ICALL_PI_P)
3706                 MINT_IN_CASE(MINT_ICALL_PPP_V)
3707                 MINT_IN_CASE(MINT_ICALL_PPI_V)
3708                         sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
3709                         if (frame->ex != NULL)
3710                                 goto handle_exception;
3711                         ip += 2;
3712                         MINT_IN_BREAK;
3713                 MINT_IN_CASE(MINT_MONO_LDPTR) 
3714                         sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
3715                         ip += 2;
3716                         ++sp;
3717                         MINT_IN_BREAK;
3718                 MINT_IN_CASE(MINT_MONO_NEWOBJ)
3719                         sp->data.p = mono_object_new_checked (context->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
3720                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3721                         ip += 2;
3722                         sp++;
3723                         MINT_IN_BREAK;
3724                 MINT_IN_CASE(MINT_MONO_FREE)
3725                         ++ip;
3726                         --sp;
3727                         g_error ("that doesn't seem right");
3728                         g_free (sp->data.p);
3729                         MINT_IN_BREAK;
3730                 MINT_IN_CASE(MINT_MONO_RETOBJ)
3731                         ++ip;
3732                         sp--;
3733                         stackval_from_data (mono_method_signature (frame->runtime_method->method)->ret, frame->retval, sp->data.p,
3734                              mono_method_signature (frame->runtime_method->method)->pinvoke);
3735                         if (sp > frame->stack)
3736                                 g_warning ("retobj: more values on stack: %d", sp-frame->stack);
3737                         goto exit_frame;
3738
3739 #define RELOP(datamem, op) \
3740         --sp; \
3741         sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
3742         ++ip;
3743                 MINT_IN_CASE(MINT_CEQ_I4)
3744                         RELOP(i, ==);
3745                         MINT_IN_BREAK;
3746                 MINT_IN_CASE(MINT_CEQ0_I4)
3747                         sp [-1].data.i = (sp [-1].data.i == 0);
3748                         ++ip;
3749                         MINT_IN_BREAK;
3750                 MINT_IN_CASE(MINT_CEQ_I8)
3751                         RELOP(l, ==);
3752                         MINT_IN_BREAK;
3753                 MINT_IN_CASE(MINT_CEQ_R8)
3754                         --sp; 
3755                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3756                                 sp [-1].data.i = 0;
3757                         else
3758                                 sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
3759                         ++ip;
3760                         MINT_IN_BREAK;
3761                 MINT_IN_CASE(MINT_CGT_I4)
3762                         RELOP(i, >);
3763                         MINT_IN_BREAK;
3764                 MINT_IN_CASE(MINT_CGT_I8)
3765                         RELOP(l, >);
3766                         MINT_IN_BREAK;
3767                 MINT_IN_CASE(MINT_CGT_R8)
3768                         --sp; 
3769                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3770                                 sp [-1].data.i = 0;
3771                         else
3772                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3773                         ++ip;
3774                         MINT_IN_BREAK;
3775
3776 #define RELOP_CAST(datamem, op, type) \
3777         --sp; \
3778         sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3779         ++ip;
3780
3781                 MINT_IN_CASE(MINT_CGT_UN_I4)
3782                         RELOP_CAST(i, >, guint32);
3783                         MINT_IN_BREAK;
3784                 MINT_IN_CASE(MINT_CGT_UN_I8)
3785                         RELOP_CAST(l, >, guint64);
3786                         MINT_IN_BREAK;
3787                 MINT_IN_CASE(MINT_CGT_UN_R8)
3788                         --sp; 
3789                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3790                                 sp [-1].data.i = 1;
3791                         else
3792                                 sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
3793                         ++ip;
3794                         MINT_IN_BREAK;
3795                 MINT_IN_CASE(MINT_CLT_I4)
3796                         RELOP(i, <);
3797                         MINT_IN_BREAK;
3798                 MINT_IN_CASE(MINT_CLT_I8)
3799                         RELOP(l, <);
3800                         MINT_IN_BREAK;
3801                 MINT_IN_CASE(MINT_CLT_R8)
3802                         --sp; 
3803                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3804                                 sp [-1].data.i = 0;
3805                         else
3806                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3807                         ++ip;
3808                         MINT_IN_BREAK;
3809                 MINT_IN_CASE(MINT_CLT_UN_I4)
3810                         RELOP_CAST(i, <, guint32);
3811                         MINT_IN_BREAK;
3812                 MINT_IN_CASE(MINT_CLT_UN_I8)
3813                         RELOP_CAST(l, <, guint64);
3814                         MINT_IN_BREAK;
3815                 MINT_IN_CASE(MINT_CLT_UN_R8)
3816                         --sp; 
3817                         if (isunordered (sp [-1].data.f, sp [0].data.f))
3818                                 sp [-1].data.i = 1;
3819                         else
3820                                 sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
3821                         ++ip;
3822                         MINT_IN_BREAK;
3823                 MINT_IN_CASE(MINT_LDFTN) {
3824                         sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
3825                         ++sp;
3826                         ip += 2;
3827                         MINT_IN_BREAK;
3828                 }
3829                 MINT_IN_CASE(MINT_LDVIRTFTN) {
3830                         RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
3831                         ip += 2;
3832                         --sp;
3833                         if (!sp->data.p)
3834                                 THROW_EX (mono_get_exception_null_reference (), ip - 2);
3835                                 
3836                         sp->data.p = get_virtual_method (context->domain, m, sp->data.p);
3837                         ++sp;
3838                         MINT_IN_BREAK;
3839                 }
3840
3841 #define LDARG(datamem, argtype) \
3842         sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
3843         ip += 2; \
3844         ++sp; 
3845         
3846                 MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
3847                 MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
3848                 MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
3849                 MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
3850                 MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
3851                 MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
3852                 MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
3853                 MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
3854                 MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
3855                 MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
3856
3857                 MINT_IN_CASE(MINT_LDARG_VT)
3858                         sp->data.p = vt_sp;
3859                         i32 = READ32(ip + 2);
3860                         memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
3861                         vt_sp += (i32 + 7) & ~7;
3862                         ip += 4;
3863                         ++sp;
3864                         MINT_IN_BREAK;
3865
3866 #define STARG(datamem, argtype) \
3867         --sp; \
3868         * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3869         ip += 2; \
3870         
3871                 MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
3872                 MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
3873                 MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
3874                 MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
3875                 MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
3876                 MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
3877                 MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
3878                 MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
3879                 MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
3880                 MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
3881
3882                 MINT_IN_CASE(MINT_STARG_VT) 
3883                         i32 = READ32(ip + 2);
3884                         --sp;
3885                         memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
3886                         vt_sp -= (i32 + 7) & ~7;
3887                         ip += 4;
3888                         MINT_IN_BREAK;
3889
3890 #define STINARG(datamem, argtype) \
3891         do { \
3892                 int n = * (guint16 *)(ip + 1); \
3893                 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
3894                 ip += 2; \
3895         } while (0)
3896         
3897                 MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
3898                 MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
3899                 MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
3900                 MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
3901                 MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
3902                 MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
3903                 MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
3904                 MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
3905                 MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
3906                 MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
3907
3908                 MINT_IN_CASE(MINT_STINARG_VT) {
3909                         int n = * (guint16 *)(ip + 1);
3910                         i32 = READ32(ip + 2);
3911                         memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
3912                         ip += 4;
3913                         MINT_IN_BREAK;
3914                 }
3915
3916                 MINT_IN_CASE(MINT_LDARGA)
3917                         sp->data.p = frame->args + * (guint16 *)(ip + 1);
3918                         ip += 2;
3919                         ++sp;
3920                         MINT_IN_BREAK;
3921
3922 #define LDLOC(datamem, argtype) \
3923         sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
3924         ip += 2; \
3925         ++sp; 
3926         
3927                 MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
3928                 MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
3929                 MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
3930                 MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
3931                 MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
3932                 MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
3933                 MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
3934                 MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
3935                 MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
3936                 MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
3937
3938                 MINT_IN_CASE(MINT_LDLOC_VT)
3939                         sp->data.p = vt_sp;
3940                         i32 = READ32(ip + 2);
3941                         memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
3942                         vt_sp += (i32 + 7) & ~7;
3943                         ip += 4;
3944                         ++sp;
3945                         MINT_IN_BREAK;
3946
3947                 MINT_IN_CASE(MINT_LDLOCA_S)
3948                         sp->data.p = locals + * (guint16 *)(ip + 1);
3949                         ip += 2;
3950                         ++sp;
3951                         MINT_IN_BREAK;
3952
3953 #define STLOC(datamem, argtype) \
3954         --sp; \
3955         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3956         ip += 2;
3957         
3958                 MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
3959                 MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
3960                 MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
3961                 MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
3962                 MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
3963                 MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
3964                 MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
3965                 MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
3966                 MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
3967                 MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
3968
3969 #define STLOC_NP(datamem, argtype) \
3970         * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
3971         ip += 2;
3972
3973                 MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
3974                 MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
3975
3976                 MINT_IN_CASE(MINT_STLOC_VT)
3977                         i32 = READ32(ip + 2);
3978                         --sp;
3979                         memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
3980                         vt_sp -= (i32 + 7) & ~7;
3981                         ip += 4;
3982                         MINT_IN_BREAK;
3983
3984                 MINT_IN_CASE(MINT_LOCALLOC) {
3985                         if (sp != frame->stack + 1) /*FIX?*/
3986                                 THROW_EX (mono_get_exception_execution_engine (NULL), ip);
3987
3988                         int len = sp [-1].data.i;
3989                         sp [-1].data.p = alloca (len);
3990                         MonoMethodHeader *header = mono_method_get_header_checked (frame->runtime_method->method, &error);
3991                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3992                         if (header->init_locals)
3993                                 memset (sp [-1].data.p, 0, len);
3994                         ++ip;
3995                         MINT_IN_BREAK;
3996                 }
3997 #if 0
3998                 MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
3999 #endif
4000                 MINT_IN_CASE(MINT_INITOBJ)
4001                         --sp;
4002                         memset (sp->data.vt, 0, READ32(ip + 1));
4003                         ip += 3;
4004                         MINT_IN_BREAK;
4005                 MINT_IN_CASE(MINT_CPBLK)
4006                         sp -= 3;
4007                         if (!sp [0].data.p || !sp [1].data.p)
4008                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4009                         ++ip;
4010                         /* FIXME: value and size may be int64... */
4011                         memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
4012                         MINT_IN_BREAK;
4013 #if 0
4014                 MINT_IN_CASE(MINT_CONSTRAINED_) {
4015                         guint32 token;
4016                         /* FIXME: implement */
4017                         ++ip;
4018                         token = READ32 (ip);
4019                         ip += 2;
4020                         MINT_IN_BREAK;
4021                 }
4022 #endif
4023                 MINT_IN_CASE(MINT_INITBLK)
4024                         sp -= 3;
4025                         if (!sp [0].data.p)
4026                                 THROW_EX (mono_get_exception_null_reference(), ip - 1);
4027                         ++ip;
4028                         /* FIXME: value and size may be int64... */
4029                         memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
4030                         MINT_IN_BREAK;
4031 #if 0
4032                 MINT_IN_CASE(MINT_NO_)
4033                         /* FIXME: implement */
4034                         ip += 2;
4035                         MINT_IN_BREAK;
4036 #endif
4037                 MINT_IN_CASE(MINT_RETHROW)
4038                         /* 
4039                          * need to clarify what this should actually do:
4040                          * start the search from the last found handler in
4041                          * this method or continue in the caller or what.
4042                          * Also, do we need to run finally/fault handlers after a retrow?
4043                          * Well, this implementation will follow the usual search
4044                          * for an handler, considering the current ip as throw spot.
4045                          * We need to NULL frame->ex_handler for the later code to
4046                          * actually run the new found handler.
4047                          */
4048                         frame->ex_handler = NULL;
4049                         THROW_EX (frame->ex, ip - 1);
4050                         MINT_IN_BREAK;
4051                 MINT_IN_DEFAULT
4052                         g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
4053                         THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
4054                 }
4055         }
4056
4057         g_assert_not_reached ();
4058         /*
4059          * Exception handling code.
4060          * The exception object is stored in frame->ex.
4061          */
4062
4063         handle_exception:
4064         {
4065                 int i;
4066                 guint32 ip_offset;
4067                 MonoInvocation *inv;
4068                 MonoExceptionClause *clause;
4069                 /*char *message;*/
4070                 MonoObject *ex_obj;
4071
4072 #if DEBUG_INTERP
4073                 if (tracing)
4074                         g_print ("* Handling exception '%s' at IL_%04x\n", 
4075                                 frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name, 
4076                                 rtm == NULL ? 0 : frame->ip - rtm->code);
4077 #endif
4078                 if (die_on_exception)
4079                         goto die_on_ex;
4080
4081                 for (inv = frame; inv; inv = inv->parent) {
4082                         MonoMethod *method;
4083                         if (inv->runtime_method == NULL)
4084                                 continue;
4085                         method = inv->runtime_method->method;
4086                         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
4087                                 continue;
4088                         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
4089                                 continue;
4090                         if (inv->ip == NULL)
4091                                 continue;
4092                         ip_offset = inv->ip - inv->runtime_method->code;
4093                         inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one  - this one wins */
4094                         for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
4095                                 clause = &inv->runtime_method->clauses [i];
4096                                 if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4097                                         if (!clause->flags) {
4098                                                 MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
4099                                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4100                                                 if (isinst_obj) {
4101                                                         /* 
4102                                                          * OK, we found an handler, now we need to execute the finally
4103                                                          * and fault blocks before branching to the handler code.
4104                                                          */
4105                                                         inv->ex_handler = clause;
4106 #if DEBUG_INTERP
4107                                                         if (tracing)
4108                                                                 g_print ("* Found handler at '%s'\n", method->name);
4109 #endif
4110                                                         goto handle_finally;
4111                                                 }
4112                                         } else {
4113                                                 g_error ("FIXME: handle filter clause");
4114                                         }
4115                                 }
4116                         }
4117                 }
4118                 /*
4119                  * If we get here, no handler was found: print a stack trace.
4120                  */
4121                 for (inv = frame; inv; inv = inv->parent) {
4122                         if (inv->invoke_trap)
4123                                 goto handle_finally;
4124                 }
4125 die_on_ex:
4126                 ex_obj = (MonoObject *) frame->ex;
4127                 mono_unhandled_exception (ex_obj);
4128                 MonoJitTlsData *jit_tls = (MonoJitTlsData *) mono_tls_get_jit_tls ();
4129                 jit_tls->abort_func (ex_obj);
4130                 g_assert_not_reached ();
4131         }
4132         handle_finally:
4133         {
4134                 int i;
4135                 guint32 ip_offset;
4136                 MonoExceptionClause *clause;
4137                 GSList *old_list = finally_ips;
4138                 MonoMethod *method = frame->runtime_method->method;
4139                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4140                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4141                 
4142 #if DEBUG_INTERP
4143                 if (tracing)
4144                         g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
4145 #endif
4146                 if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
4147                                 || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
4148                         goto exit_frame;
4149                 }
4150                 ip_offset = frame->ip - rtm->code;
4151
4152                 if (endfinally_ip != NULL)
4153                         finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
4154                 for (i = 0; i < header->num_clauses; ++i)
4155                         if (frame->ex_handler == &rtm->clauses [i])
4156                                 break;
4157                 while (i > 0) {
4158                         --i;
4159                         clause = &rtm->clauses [i];
4160                         if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
4161                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
4162                                         ip = rtm->code + clause->handler_offset;
4163                                         finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
4164 #if DEBUG_INTERP
4165                                         if (tracing)
4166                                                 g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
4167 #endif
4168                                 }
4169                         }
4170                 }
4171
4172                 endfinally_ip = NULL;
4173
4174                 if (old_list != finally_ips && finally_ips) {
4175                         ip = finally_ips->data;
4176                         finally_ips = g_slist_remove (finally_ips, ip);
4177                         sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
4178                         goto main_loop;
4179                 }
4180
4181                 /*
4182                  * If an exception is set, we need to execute the fault handler, too,
4183                  * otherwise, we continue normally.
4184                  */
4185                 if (frame->ex)
4186                         goto handle_fault;
4187                 ves_abort();
4188         }
4189         handle_fault:
4190         {
4191                 int i;
4192                 guint32 ip_offset;
4193                 MonoExceptionClause *clause;
4194                 MonoMethod *method = frame->runtime_method->method;
4195                 MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
4196                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4197                 
4198 #if DEBUG_INTERP
4199                 if (tracing)
4200                         g_print ("* Handle fault\n");
4201 #endif
4202                 ip_offset = frame->ip - rtm->code;
4203                 for (i = 0; i < header->num_clauses; ++i) {
4204                         clause = &rtm->clauses [i];
4205                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
4206                                 ip = rtm->code + clause->handler_offset;
4207 #if DEBUG_INTERP
4208                                 if (tracing)
4209                                         g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
4210 #endif
4211                                 goto main_loop;
4212                         }
4213                 }
4214                 /*
4215                  * If the handler for the exception was found in this method, we jump
4216                  * to it right away, otherwise we return and let the caller run
4217                  * the finally, fault and catch blocks.
4218                  * This same code should be present in the endfault opcode, but it
4219                  * is corrently not assigned in the ECMA specs: LAMESPEC.
4220                  */
4221                 if (frame->ex_handler) {
4222 #if DEBUG_INTERP
4223                         if (tracing)
4224                                 g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
4225 #endif
4226                         ip = rtm->code + frame->ex_handler->handler_offset;
4227                         sp = frame->stack;
4228                         vt_sp = (unsigned char *) sp + rtm->stack_size;
4229                         sp->data.p = frame->ex;
4230                         ++sp;
4231                         goto main_loop;
4232                 }
4233                 goto exit_frame;
4234         }
4235 exit_frame:
4236         DEBUG_LEAVE ();
4237 }
4238
4239 void
4240 ves_exec_method (MonoInvocation *frame)
4241 {
4242         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
4243         ThreadContext context_struct;
4244         MonoError error;
4245         jmp_buf env;
4246
4247         frame->ex = NULL;
4248
4249         if (setjmp(env)) {
4250                 mono_unhandled_exception ((MonoObject*)frame->ex);
4251                 return;
4252         }
4253         if (context == NULL) {
4254                 context = &context_struct;
4255                 context_struct.domain = mono_domain_get ();
4256                 context_struct.base_frame = frame;
4257                 context_struct.current_frame = NULL;
4258                 context_struct.env_frame = frame;
4259                 context_struct.current_env = &env;
4260                 context_struct.search_for_handler = 0;
4261                 context_struct.managed_code = 0;
4262                 mono_native_tls_set_value (thread_context_id, context);
4263         }
4264         frame->ip = NULL;
4265         frame->parent = context->current_frame;
4266         frame->runtime_method = mono_interp_get_runtime_method (context->domain, frame->method, &error);
4267         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4268         context->managed_code = 1;
4269         ves_exec_method_with_context (frame, context);
4270         context->managed_code = 0;
4271         if (frame->ex) {
4272                 if (context != &context_struct && context->current_env) {
4273                         context->env_frame->ex = frame->ex;
4274                         longjmp (*context->current_env, 1);
4275                 }
4276                 else
4277                         mono_unhandled_exception ((MonoObject*)frame->ex);
4278         }
4279         if (context->base_frame == frame)
4280                 mono_native_tls_set_value (thread_context_id, NULL);
4281         else
4282                 context->current_frame = frame->parent;
4283 }
4284
4285 static int 
4286 ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4287 {
4288         MonoImage *image = mono_assembly_get_image (assembly);
4289         MonoMethod *method;
4290         MonoError error;
4291         int rval;
4292
4293         method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, &error);
4294         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4295
4296         if (!method)
4297                 g_error ("No entry point method found in %s", mono_image_get_filename (image));
4298
4299         rval = mono_runtime_run_main_checked (method, argc, argv, &error);
4300         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4301         return rval;
4302 }
4303
4304 static void
4305 usage (void)
4306 {
4307         fprintf (stderr,
4308                  "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4309                  "Usage is: mint [options] executable args...\n\n", VERSION);
4310         fprintf (stderr,
4311                  "Runtime Debugging:\n"
4312 #ifdef DEBUG_INTERP
4313                  "   --debug\n"
4314 #endif
4315                  "   --dieonex\n"
4316                  "   --noptr\t\t\tdon't print pointer addresses in trace output\n"
4317                  "   --opcode-count\n"
4318                  "   --print-vtable\n"
4319                  "   --traceclassinit\n"
4320                  "\n"
4321                  "Development:\n"
4322                  "   --debug method_name\n"
4323                  "   --profile\n"
4324                  "   --trace\n"
4325                  "   --traceops\n"
4326                  "   --regression\n"
4327                  "\n"
4328                  "Runtime:\n"
4329                  "   --config filename  load the specified config file instead of the default\n"
4330                  "   --workers n        maximum number of worker threads\n"
4331                 );
4332         exit (1);
4333 }
4334
4335 static MonoBoolean
4336 interp_ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
4337                           MonoReflectionMethod **method, 
4338                           gint32 *iloffset, gint32 *native_offset,
4339                           MonoString **file, gint32 *line, gint32 *column)
4340 {
4341         ThreadContext *context = mono_native_tls_get_value (thread_context_id);
4342         MonoInvocation *inv = context->current_frame;
4343         MonoError error;
4344         int i;
4345
4346         for (i = 0; inv && i < skip; inv = inv->parent)
4347                 if (inv->runtime_method != NULL)
4348                         ++i;
4349
4350         if (iloffset)
4351                 *iloffset = 0;
4352         if (native_offset)
4353                 *native_offset = 0;
4354         if (method) {
4355                 if (inv == NULL) {
4356                         *method = NULL;
4357                 } else {
4358                         *method = mono_method_get_object_checked (context->domain, inv->runtime_method->method, NULL, &error);
4359                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4360                 }
4361         }
4362         if (line)
4363                 *line = 0;
4364         if (need_file_info) {
4365                 if (column)
4366                         *column = 0;
4367                 if (file)
4368                         *file = mono_string_new (mono_domain_get (), "unknown");
4369         }
4370
4371         return TRUE;
4372 }
4373
4374 static MonoArray *
4375 interp_ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
4376 {
4377         MonoDomain *domain = mono_domain_get ();
4378         MonoArray *res;
4379         MonoArray *ta = exc->trace_ips;
4380         MonoError error;
4381         int i, len;
4382
4383         if (ta == NULL) {
4384                 /* Exception is not thrown yet */
4385                 MonoArray *array = mono_array_new_checked (domain, mono_defaults.stack_frame_class, 0, &error);
4386                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4387                 return array;
4388         }
4389         
4390         len = mono_array_length (ta);
4391
4392         res = mono_array_new_checked (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0, &error);
4393         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4394
4395         for (i = skip; i < len / 2; i++) {
4396                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
4397                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4398                 gushort *ip = mono_array_get (ta, gpointer, 2 * i + 1);
4399                 RuntimeMethod *rtm = mono_array_get (ta, gpointer, 2 * i);
4400
4401                 if (rtm != NULL) {
4402                         sf->method = mono_method_get_object_checked (domain, rtm->method, NULL, &error);
4403                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
4404                         sf->native_offset = ip - rtm->code;
4405                 }
4406
4407 #if 0
4408                 sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
4409
4410                 if (need_file_info) {
4411                         gchar *filename;
4412                         
4413                         filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
4414
4415                         sf->filename = filename? mono_string_new (domain, filename): NULL;
4416                         sf->column = 0;
4417
4418                         g_free (filename);
4419                 }
4420 #endif
4421
4422                 mono_array_set (res, gpointer, i, sf);
4423         }
4424
4425         return res;
4426 }
4427
4428 void
4429 mono_interp_init ()
4430 {
4431         mono_native_tls_alloc (&thread_context_id, NULL);
4432     mono_native_tls_set_value (thread_context_id, NULL);
4433         mono_os_mutex_init_recursive (&create_method_pointer_mutex);
4434
4435         mono_interp_transform_init ();
4436 }
4437
4438 typedef int (*TestMethod) (void);
4439
4440 static void
4441 interp_regression_step (MonoImage *image, int verbose, int *total_run, int *total, GTimer *timer, MonoDomain *domain)
4442 {
4443         int result, expected, failed, cfailed, run;
4444         double elapsed, transform_time;
4445         int i;
4446         MonoObject *result_obj;
4447         static gboolean filter_method_init = FALSE;
4448         static const char *filter_method = NULL;
4449
4450         g_print ("Test run: image=%s\n", mono_image_get_filename (image));
4451         cfailed = failed = run = 0;
4452         transform_time = elapsed = 0.0;
4453
4454         g_timer_start (timer);
4455         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4456                 MonoObject *exc = NULL;
4457                 MonoError error;
4458                 MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4459                 if (!method) {
4460                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
4461                         continue;
4462                 }
4463
4464                 if (!filter_method_init) {
4465                         filter_method = g_getenv ("INTERP_FILTER_METHOD");
4466                         filter_method_init = TRUE;
4467                 }
4468                 gboolean filter = FALSE;
4469                 if (filter_method) {
4470                         const char *name = filter_method;
4471
4472                         if ((strchr (name, '.') > name) || strchr (name, ':')) {
4473                                 MonoMethodDesc *desc = mono_method_desc_new (name, TRUE);
4474                                 filter = mono_method_desc_full_match (desc, method);
4475                                 mono_method_desc_free (desc);
4476                         } else {
4477                                 filter = strcmp (method->name, name) == 0;
4478                         }
4479                 } else { /* no filter, check for `Category' attribute on method */
4480                         filter = TRUE;
4481                         MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
4482                         mono_error_cleanup (&error);
4483
4484                         if (ainfo) {
4485                                 int j;
4486                                 for (j = 0; j < ainfo->num_attrs && filter; ++j) {
4487                                         MonoCustomAttrEntry *centry = &ainfo->attrs [j];
4488                                         if (centry->ctor == NULL)
4489                                                 continue;
4490
4491                                         MonoClass *klass = centry->ctor->klass;
4492                                         if (strcmp (klass->name, "CategoryAttribute"))
4493                                                 continue;
4494
4495                                         MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
4496                                         /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
4497                                          * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
4498                                         mono_error_cleanup (&error);
4499                                         MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
4500                                         MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
4501                                         mono_error_cleanup (&error);
4502                                         char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
4503                                         mono_error_cleanup (&error);
4504                                         if (!strcmp (utf8_str, "!INTERPRETER")) {
4505                                                 g_print ("skip %s...\n", method->name);
4506                                                 filter = FALSE;
4507                                         }
4508                                 }
4509                         }
4510                 }
4511                 if (strncmp (method->name, "test_", 5) == 0 && filter) {
4512                         MonoError interp_error;
4513                         MonoObject *exc = NULL;
4514
4515                         result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
4516                         if (!mono_error_ok (&interp_error)) {
4517                                 cfailed++;
4518                                 g_print ("Test '%s' execution failed.\n", method->name);
4519                         } else if (exc != NULL) {
4520                                 g_print ("Exception in Test '%s' occured:\n", method->name);
4521                                 mono_object_describe (exc);
4522                                 run++;
4523                                 failed++;
4524                         } else {
4525                                 result = *(gint32 *) mono_object_unbox (result_obj);
4526                                 expected = atoi (method->name + 5);  // FIXME: oh no.
4527                                 run++;
4528
4529                                 if (result != expected) {
4530                                         failed++;
4531                                         g_print ("Test '%s' failed result (got %d, expected %d).\n", method->name, result, expected);
4532                                 }
4533                         }
4534                 }
4535         }
4536         g_timer_stop (timer);
4537         elapsed = g_timer_elapsed (timer, NULL);
4538         if (failed > 0 || cfailed > 0){
4539                 g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
4540                                 run, failed, cfailed, 100.0*(run-failed-cfailed)/run);
4541         } else {
4542                 g_print ("Results: total tests: %d, all pass \n",  run);
4543         }
4544
4545         g_print ("Elapsed time: %f secs (%f, %f)\n\n", elapsed,
4546                         elapsed - transform_time, transform_time);
4547         *total += failed + cfailed;
4548         *total_run += run;
4549 }
4550 static int
4551 interp_regression (MonoImage *image, int verbose, int *total_run)
4552 {
4553         MonoMethod *method;
4554         GTimer *timer = g_timer_new ();
4555         MonoDomain *domain = mono_domain_get ();
4556         guint32 i;
4557         int total;
4558
4559         /* load the metadata */
4560         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4561                 MonoError error;
4562                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4563                 if (!method) {
4564                         mono_error_cleanup (&error);
4565                         continue;
4566                 }
4567                 mono_class_init (method->klass);
4568         }
4569
4570         total = 0;
4571         *total_run = 0;
4572         interp_regression_step (image, verbose, total_run, &total, timer, domain);
4573
4574         g_timer_destroy (timer);
4575         return total;
4576 }
4577
4578 int
4579 mono_interp_regression_list (int verbose, int count, char *images [])
4580 {
4581         int i, total, total_run, run;
4582         
4583         total_run = total = 0;
4584         for (i = 0; i < count; ++i) {
4585                 MonoAssembly *ass = mono_assembly_open_predicate (images [i], FALSE, FALSE, NULL, NULL, NULL);
4586                 if (!ass) {
4587                         g_warning ("failed to load assembly: %s", images [i]);
4588                         continue;
4589                 }
4590                 total += interp_regression (mono_assembly_get_image (ass), verbose, &run);
4591                 total_run += run;
4592         }
4593         if (total > 0) {
4594                 g_print ("Overall results: tests: %d, failed: %d (pass: %.2f%%)\n", total_run, total, 100.0*(total_run-total)/total_run);
4595         } else {
4596                 g_print ("Overall results: tests: %d, 100%% pass\n", total_run);
4597         }
4598         
4599         return total;
4600 }
4601