2002-04-18 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / jit / jit.c
index 03684a4f5f46ea3cb897b9308f3297274b1ccb59..f43c9a7bd7a3eb54187f52a4bdf97c2f9a58949f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * testjit.c: The mono JIT compiler.
+ * jit.c: The mono JIT compiler.
  *
  * Author:
  *   Dietmar Maurer (dietmar@ximian.com)
@@ -8,18 +8,23 @@
  */
 
 #include <config.h>
+#if HAVE_BOEHM_GC
+#include <gc/gc.h>
+#endif
 #include <glib.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <mono/metadata/verify.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/loader.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/class.h>
 #include <mono/metadata/object.h>
+#include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/opcodes.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/tokentype.h>
@@ -46,12 +51,6 @@ enum {
 };
 #undef OPDEF
 
-#define OPDEF(a,b,c,d,e,f,g,h,i,j) b,
-static char *opcode_names [] = {
-#include "mono/cil/opcode.def" 
-};
-#undef OPDEF
-
 #define SET_VARINFO(vi,t,k,o,s) do { vi.type=t; vi.kind=k; vi.offset=o; vi.size=s; } while (0)
 
 #define MAKE_CJUMP(name)                                                      \
@@ -91,7 +90,6 @@ case CEE_##cname: {                                                           \
        ++ip;                                                                 \
        sp -= 2;                                                              \
        t1 = mono_ctree_new (mp, MB_TERM_##cname, sp [0], sp [1]);            \
-        g_assert (sp [0]->svt == sp [1]->svt);                                \
        PUSH_TREE (t1, VAL_I32);                                              \
        break;                                                                \
 }
@@ -101,7 +99,6 @@ case CEE_##name: {                                                            \
        ++ip;                                                                 \
        sp -= 2;                                                              \
        t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]);             \
-        g_assert (sp [0]->svt == sp [1]->svt);                                \
         t1->svt = sp [0]->svt;                                                \
         t1 = mono_store_tree (cfg, -1, t1, &t2);                              \
         g_assert (t1);                                                        \
@@ -191,19 +188,41 @@ gboolean mono_jit_dump_forest = FALSE;
 /* Whether to print function call traces */
 gboolean mono_jit_trace_calls = FALSE;
 
+/* Whether to insert in the code profile callbacks */
+gboolean mono_jit_profile = FALSE;
+
 /* Force jit to share code between application domains */
 gboolean mono_jit_share_code = FALSE;
 
+/* maximum number of worker threads */
+int mono_worker_threads = 1;
+
 MonoDebugHandle *mono_debug_handle = NULL;
 GList *mono_debug_methods = NULL;
 
-gpointer mono_end_of_stack = NULL;
+/* If non-zero, insert a breakpoint when compiling the next method.
+ * If positive, interpret this variable as a counter and decrement
+ * it after setting the breakpoint. */
+int mono_debug_insert_breakpoint = 0;
 
-MonoJitInfoTable *mono_jit_info_table = NULL;
+/* This is the address of the last breakpoint which was inserted. */
+gchar *mono_debug_last_breakpoint_address = NULL;
+
+gpointer mono_end_of_stack = NULL;
 
 /* last managed frame (used by pinvoke) */ 
 guint32 lmf_thread_id = 0;
 
+/* used to store a function pointer called after uncatched exceptions */ 
+guint32 exc_cleanup_id = 0;
+
+/* stores a pointer to async result used by exceptions */ 
+guint32 async_result_id = 0;
+
+MonoJitStats mono_jit_stats;
+
+CRITICAL_SECTION *metadata_section = NULL;
+
 /* 
  * We sometimes need static data, for example the forest generator need it to
  * store constants or class data.
@@ -221,98 +240,6 @@ mono_alloc_static0 (int size)
 
 typedef void (*MonoCCtor) (void);
 
-MonoJitInfoTable *
-mono_jit_info_table_new ()
-{
-       return g_array_new (FALSE, FALSE, sizeof (gpointer));
-}
-
-int
-mono_jit_info_table_index (MonoJitInfoTable *table, gpointer addr)
-{
-       int left = 0, right = table->len;
-
-       while (left < right) {
-               int pos = (left + right) / 2;
-               MonoJitInfo *ji = g_array_index (table, gpointer, pos);
-               gpointer start = ji->code_start;
-               gpointer end = start + ji->code_size;
-
-               if (addr < start)
-                       right = pos;
-               else if (addr >= end) 
-                       left = pos + 1;
-               else
-                       return pos;
-       }
-
-       return left;
-}
-
-MonoJitInfo *
-mono_jit_info_table_find (MonoJitInfoTable *table, gpointer addr)
-{
-       int left = 0, right = table->len;
-
-       while (left < right) {
-               int pos = (left + right) / 2;
-               MonoJitInfo *ji = g_array_index (table, gpointer, pos);
-               gpointer start = ji->code_start;
-               gpointer end = start + ji->code_size;
-
-               if (addr < start)
-                       right = pos;
-               else if (addr >= end) 
-                       left = pos + 1;
-               else
-                       return ji;
-       }
-
-       return NULL;
-}
-
-void
-mono_jit_info_table_add (MonoJitInfoTable *table, MonoJitInfo *ji)
-{
-       gpointer start = ji->code_start;
-       int pos = mono_jit_info_table_index (table, start);
-
-       //printf ("TESTADD %d %p\n", pos, ji->code_start);
-       g_array_insert_val (table, pos, ji);
-}
-
-/**
- * runtime_class_init:
- * @klass: the class to initialise
- *
- * Initialise the class @klass by calling the class constructor.
- */
-static void
-runtime_class_init (MonoClass *klass)
-{
-       MonoCCtor cctor;
-       MonoMethod *method;
-       int i;
-
-       if (mono_debug_handle)
-               mono_debug_add_type (mono_debug_handle, klass);
-       
-       for (i = 0; i < klass->method.count; ++i) {
-               method = klass->methods [i];
-               if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
-                   (strcmp (".cctor", method->name) == 0)) {
-       
-                       cctor = arch_compile_method (method);
-                       if (!cctor && mono_debug_handle)
-                               return;
-                       g_assert (cctor != NULL);
-                       cctor ();
-                       return;
-               }
-       }
-       /* No class constructor found */
-}
-
 static int
 map_store_svt_type (int svt)
 {
@@ -386,6 +313,61 @@ map_stind_type (MonoType *type)
        return -1;
 }
 
+/**
+ * map_remote_stind_type:
+ * @type: the type to map
+ *
+ * Translates the MonoType @type into the corresponding remote store opcode 
+ * for the code generator.
+ */
+static int
+map_remote_stind_type (MonoType *type)
+{
+       if (type->byref) {
+               return MB_TERM_REMOTE_STIND_REF;
+       }
+
+       switch (type->type) {
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+               return MB_TERM_REMOTE_STIND_I1; 
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+               return MB_TERM_REMOTE_STIND_I2; 
+       case MONO_TYPE_I:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+               return MB_TERM_REMOTE_STIND_I4; 
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:    
+               return MB_TERM_REMOTE_STIND_REF;
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+               return MB_TERM_REMOTE_STIND_I8;
+       case MONO_TYPE_R4:
+               return MB_TERM_REMOTE_STIND_R4;
+       case MONO_TYPE_R8:
+               return MB_TERM_REMOTE_STIND_R8;
+       case MONO_TYPE_VALUETYPE: 
+               if (type->data.klass->enumtype)
+                       return map_remote_stind_type (type->data.klass->enum_basetype);
+               else
+                       return MB_TERM_REMOTE_STIND_OBJ;
+       default:
+               g_warning ("unknown type %02x", type->type);
+               g_assert_not_reached ();
+       }
+
+       g_assert_not_reached ();
+       return -1;
+}
+
 static int
 map_starg_type (MonoType *type)
 {
@@ -432,7 +414,7 @@ map_starg_type (MonoType *type)
 }
 
 static int
-map_arg_type (MonoType *type, gboolean pinvoke)
+map_arg_type (MonoType *type)
 {
        if (type->byref) 
                return MB_TERM_ARG_I4;
@@ -445,6 +427,7 @@ map_arg_type (MonoType *type, gboolean pinvoke)
        case MONO_TYPE_U2:
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I:
+       case MONO_TYPE_U:
        case MONO_TYPE_I4:
        case MONO_TYPE_U4:
        case MONO_TYPE_CLASS:
@@ -454,8 +437,6 @@ map_arg_type (MonoType *type, gboolean pinvoke)
        case MONO_TYPE_ARRAY:    
                return MB_TERM_ARG_I4;
        case MONO_TYPE_STRING:
-               if (pinvoke)
-                       return MB_TERM_ARG_STRING;
                return MB_TERM_ARG_I4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
@@ -466,7 +447,7 @@ map_arg_type (MonoType *type, gboolean pinvoke)
                return MB_TERM_ARG_R8;
        case MONO_TYPE_VALUETYPE:
                if (type->data.klass->enumtype)
-                       return map_arg_type (type->data.klass->enum_basetype, pinvoke);
+                       return map_arg_type (type->data.klass->enum_basetype);
                else
                        return MB_TERM_ARG_OBJ;
        default:
@@ -744,6 +725,8 @@ arch_allocate_var (MonoFlowGraph *cfg, int size, int align, MonoValueKind kind,
 {
        MonoVarInfo vi;
 
+       mono_jit_stats.allocate_var++;
+
        switch (kind) {
        case MONO_TEMPVAR:
        case MONO_LOCALVAR: {
@@ -981,7 +964,7 @@ ctree_create_dup (MonoMemPool *mp, MBTree *s)
 }
 
 static MBTree *
-mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
+mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **tdup)
 {
        MonoMemPool *mp = cfg->mp;
        MBTree *t;
@@ -1006,17 +989,17 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
                        vnum = mono_allocate_intvar (cfg, slot, s->svt);
 
                        if (s->left->op == MB_TERM_ADDR_L && s->left->data.i == vnum) {
-                               if (dup)
-                                       *dup = ctree_create_dup (mp, s);
+                               if (tdup)
+                                       *tdup = ctree_create_dup (mp, s);
                                return NULL;
                        }
                        // fall through
                } else {
-                       if (dup)
-                               *dup = ctree_create_dup (mp, s);
+                       if (tdup)
+                               *tdup = ctree_create_dup (mp, s);
                        return NULL;
                }
-       }                       
+       }       
        default: {
                        g_assert (s->svt != VAL_UNKNOWN);
 
@@ -1036,8 +1019,8 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
                }
        }
 
-       if (dup) 
-               mono_store_tree (cfg, -1, t, dup);
+       if (tdup) 
+               mono_store_tree (cfg, -1, t, tdup);
 
        return t;
 }
@@ -1085,33 +1068,10 @@ mono_cfg_free (MonoFlowGraph *cfg)
 
        if (cfg->bblocks)
                g_free (cfg->bblocks);
-
+               
        g_array_free (cfg->varinfo, TRUE);
 }
 
-
-static void
-runtime_object_init (MonoObject *obj)
-{
-       MonoClass *klass = obj->vtable->klass;
-       MonoMethod *method = NULL;
-       void (*ctor) (gpointer this);
-       int i;
-
-       for (i = 0; i < klass->method.count; ++i) {
-               if (!strcmp (".ctor", klass->methods [i]->name) &&
-                   klass->methods [i]->signature->param_count == 0) {
-                       method = klass->methods [i];
-                       break;
-               }
-       }
-
-       g_assert (method);
-
-       ctor = arch_compile_method (method);
-       ctor (obj);
-}
-
 static MonoBBlock *
 mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, int type)
 {
@@ -1124,7 +1084,7 @@ mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, int type)
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
                if (MONO_OFFSET_IN_HANDLER (clause, ip))
-                       return NULL;
+                       continue;
 
                if (MONO_OFFSET_IN_CLAUSE (clause, ip)) {
                        if (clause->flags & type) {
@@ -1162,6 +1122,8 @@ mono_analyze_flow (MonoFlowGraph *cfg)
        ip = header->code;
        end = ip + header->code_size;
 
+       mono_jit_stats.cil_code_size += header->code_size;
+
        /* fixme: add block boundaries for exceptions */
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
@@ -1172,7 +1134,7 @@ mono_analyze_flow (MonoFlowGraph *cfg)
        while (ip < end) {
                guint32 cli_addr = ip - header->code;
 
-               //printf ("IL%04x OPCODE %s\n", cli_addr, opcode_names [*ip]);
+               //printf ("IL%04x OPCODE %s\n", cli_addr, mono_opcode_names [*ip]);
                
                if (block_end) {
                        CREATE_BLOCK (cli_addr);
@@ -1207,11 +1169,13 @@ mono_analyze_flow (MonoFlowGraph *cfg)
                case MonoInlineNone:
                        ++ip;
                        break;
+               case MonoInlineString:
+                       mono_ldstr (mono_domain_get (), method->klass->image, mono_metadata_token_index (read32 (ip + 1)));
+                       /* fall through */
                case MonoInlineType:
                case MonoInlineField:
                case MonoInlineMethod:
                case MonoInlineTok:
-               case MonoInlineString:
                case MonoInlineSig:
                case MonoShortInlineR:
                case MonoInlineI:
@@ -1356,6 +1320,263 @@ mono_array_new_va (MonoMethod *cm, ...)
        return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
 }
 
+#define INLINE_CALLS 1
+
+#ifdef INLINE_CALLS
+static MonoMethod *
+check_inlining (MonoFlowGraph *cfg, MonoMethod *method, gboolean *virtual, MBTree **stack, int n)
+{
+       MonoImage *image = method->klass->image; 
+       MonoMethodHeader *header;
+       MonoMethodSignature *csig, *sig = method->signature;
+       MonoMemPool *mp = cfg->mp;
+       MonoMethod *cm;
+       register const unsigned char *ip, *end;
+       static int c = 0;
+       guint32 token;
+       gboolean stop, v = FALSE;
+       MBTree **stack_copy, *t1;
+       int i, anum, arg_used [256];
+
+       for (i = 0; i < 4; i++)
+               arg_used [i] = 0;
+
+       g_assert (method);
+       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
+           (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+           (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+           (method->klass->marshalbyref))
+               return NULL;
+             
+       header = ((MonoMethodNormal *)method)->header;
+
+       if (!header) 
+               return NULL;
+
+       if (header->num_clauses)
+               return NULL;
+
+       ip = header->code;
+       end = ip + header->code_size;
+
+       stop = FALSE;
+        
+       while (!stop && ip < end) {
+
+               switch (*ip) {
+               case CEE_LDARG_0:
+               case CEE_LDARG_1:
+               case CEE_LDARG_2:
+               case CEE_LDARG_3: {
+                       int an = (*ip) - CEE_LDARG_0;
+                       if (arg_used [an])
+                               return NULL;
+                       arg_used [an] = TRUE;
+                       ++ip;
+                       break;
+               }       
+               case CEE_LDARG_S:
+                       ++ip;
+                       if (arg_used [*ip])
+                               return NULL;
+                       arg_used [*ip] = TRUE;
+                       ++ip;
+                       break;
+               case CEE_LDNULL:
+               case CEE_LDC_I4_M1:
+               case CEE_LDC_I4_0:
+               case CEE_LDC_I4_1:
+               case CEE_LDC_I4_2:
+               case CEE_LDC_I4_3:
+               case CEE_LDC_I4_4:
+               case CEE_LDC_I4_5:
+               case CEE_LDC_I4_6:
+               case CEE_LDC_I4_7:
+               case CEE_LDC_I4_8:
+                       ++ip;
+                       break;
+               case CEE_LDC_I4_S:
+                       ip += 2;
+                       break;
+               case CEE_LDC_I4:
+               case CEE_LDC_R4:
+                       ip += 5;
+                       break;
+               case CEE_LDC_I8:
+               case CEE_LDC_R8:
+                       ip += 9;
+                       break;
+               case CEE_CALL:
+                       stop = TRUE;
+                       break;
+               case CEE_CALLVIRT:
+                       v = TRUE;
+                       stop = TRUE;
+                       break;
+               default:
+                       return NULL;
+               }
+       }
+
+       if (ip >= end || *ip != CEE_CALL)
+               return NULL;
+
+       ++ip;
+       token = read32 (ip);
+       ip += 4;
+
+       if (ip >= end)
+               return NULL;
+
+       if (!(ip [0] == CEE_RET ||
+             ((ip + 4) < end &&
+              ip [0] == CEE_STLOC_0 &&
+              ip [1] == CEE_BR_S &&
+              ip [2] == 0 &&
+              ip [3] == CEE_LDLOC_0 &&
+              ip [4] == CEE_RET)))
+               return NULL;
+
+       cm = mono_get_method (image, token, NULL);
+       g_assert (cm);
+
+       csig = cm->signature;
+
+       if (cm == method || sig->hasthis != csig->hasthis ||
+           !mono_metadata_type_equal (sig->ret, csig->ret))
+               return NULL;
+
+       if (csig->param_count > n)
+               return NULL;
+
+       if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
+           !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
+               v = 0;
+
+       *virtual = v;
+
+       stack_copy = alloca (sizeof (MBTree *) * n);
+       memcpy (stack_copy, stack, sizeof (MBTree *) * n);
+
+       ip = header->code;
+       end = ip + header->code_size;
+
+       //printf ("C %s.%s:%s %d\n", method->klass->name_space, method->klass->name, 
+       //method->name, sig->param_count);      
+
+       //for (i = 0; i < (sig->param_count + sig->hasthis); i++)
+       //printf ("STACK0 %d %p\n", i, stack [i]);
+
+       stop = FALSE;
+       anum = 0;
+       while (!stop && ip < end) {
+
+               switch (*ip) {
+               case CEE_LDARG_0:
+               case CEE_LDARG_1:
+               case CEE_LDARG_2:
+               case CEE_LDARG_3:
+                       stack [anum] = stack_copy [(*ip) - CEE_LDARG_0];
+                       //printf ("ARG %d %p\n", anum, stack [anum]);
+                       ++ip;
+                       break;
+               case CEE_LDARG_S:
+                       ++ip;
+                       stack [anum] = stack_copy [*ip];
+                       //printf ("ARGS %d %p\n", anum, stack [anum]);
+                       ++ip;
+                       break;
+               case CEE_LDNULL:
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                       t1->data.i = 0;
+                       //printf ("CONST %d %p\n", anum, t1);
+                       stack [anum] = t1;
+                       ++ip;
+                       break;
+               case CEE_LDC_I4_M1:
+               case CEE_LDC_I4_0:
+               case CEE_LDC_I4_1:
+               case CEE_LDC_I4_2:
+               case CEE_LDC_I4_3:
+               case CEE_LDC_I4_4:
+               case CEE_LDC_I4_5:
+               case CEE_LDC_I4_6:
+               case CEE_LDC_I4_7:
+               case CEE_LDC_I4_8:
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                       t1->data.i = (*ip) - CEE_LDC_I4_0;
+                       //printf ("CONST %d %p\n", anum, t1);
+                       stack [anum] = t1;
+                       ++ip;
+                       break;
+               case CEE_LDC_I4_S:
+                       ++ip;
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                       t1->data.i = *(const gint8 *)ip;
+                       stack [anum] = t1;
+                       ++ip;
+                       break;
+               case CEE_LDC_I4: 
+                       ++ip;
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                       t1->data.i = read32 (ip);
+                       stack [anum] = t1;
+                       ip += 4;
+                       break;
+               case CEE_LDC_I8:
+                       ++ip;
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I8);
+                       t1->data.l = read64 (ip);
+                       stack [anum] = t1;
+                       ip += 8;
+                       break;
+               case CEE_LDC_R4: {
+                       float *f = mono_alloc_static (sizeof (float));
+                       ++ip;
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R4);
+                       readr4 (ip, f);
+                       t1->data.p = f;
+                       stack [anum] = t1;
+                       ip += 4;
+                       break;
+               }
+               case CEE_LDC_R8: {
+                       float *d = mono_alloc_static (sizeof (double));
+                       ++ip;
+                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R8);
+                       readr8 (ip, d);
+                       t1->data.p = d;
+                       stack [anum] = t1;
+                       ip += 8;
+                       break;
+               }
+               case CEE_CALL:
+                       stop = TRUE;
+                       break;
+               case CEE_CALLVIRT:
+                       v = TRUE;
+                       stop = TRUE;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+               anum++;
+       }
+
+       /*
+       for (i = 0; i < (csig->param_count + csig->hasthis); i++)
+               printf ("STACK1 %d %p\n", i, stack [i]);
+
+
+       printf ("C1 %s.%s:%s %d\n", method->klass->name_space, method->klass->name, 
+               method->name, c++);     
+       */
+
+       return cm;
+
+}
+#endif
+
 #define ADD_TREE(t,a)   do { t->cli_addr = a; g_ptr_array_add (forest, (t)); } while (0)
 #define PUSH_TREE(t,k)  do { int tt = k; *sp = t; t->svt = tt; sp++; } while (0)
 
@@ -1454,16 +1675,19 @@ mono_analyze_stack (MonoFlowGraph *cfg)
        int varnum = 0, firstarg = 0, retvtarg = 0;
        gboolean repeat, superblock_end;
        MonoBBlock *bb, *tbb;
+       int maxstack;
 
        header = ((MonoMethodNormal *)method)->header;
        signature = method->signature;
        image = method->klass->image; 
 
-       sp = stack = alloca (sizeof (MBTree *) * (header->max_stack + 1));
-       
+       /* we add 10 extra slots for method inlining */
+       maxstack = header->max_stack + 10;
+       sp = stack = alloca (sizeof (MBTree *) * (maxstack + 1));
+
        if (header->num_locals) {
                int size, align;
-
+               
                for (i = 0; i < header->num_locals; ++i) {
                        size = mono_type_size (header->locals [i], &align);
                        varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
@@ -1559,10 +1783,11 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                
                                        superblock_end = FALSE;
 
+
         while (ip < end) {
                guint32 cli_addr = ip - header->code;
 
-               //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, opcode_names [*ip], 
+               //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, mono_opcode_names [*ip], 
                //forest->len, superblock_end, sp - stack);
 
                switch (*ip) {
@@ -1669,17 +1894,17 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                }
                case CEE_LDSTR: {
                        MonoObject *o;
-                       guint32 index;
+                       guint32 ind;
 
                        ++ip;
-                       index = mono_metadata_token_index (read32 (ip));
+                       ind = mono_metadata_token_index (read32 (ip));
                        ip += 4;
 
                        if (cfg->share_code) {
                                t1 = mono_ctree_new_leaf (mp, MB_TERM_LDSTR);
-                               t1->data.i = index;
+                               t1->data.i = ind;
                        } else {
-                               o = (MonoObject *) mono_ldstr (cfg->domain, image, index);
+                               o = (MonoObject *) mono_ldstr (cfg->domain, image, ind);
                                t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
                                t1->data.p = o;
                        }
@@ -1754,17 +1979,23 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                field = mono_class_get_field (klass, token);
                        }
                        g_assert (field);
-
-                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
                        
-                       if (klass->valuetype)
-                               t1->data.i = field->offset - sizeof (MonoObject);
-                       else 
-                               t1->data.i = field->offset;
+                       if (klass->marshalbyref) {
+                               t1 = mono_ctree_new (mp, MB_TERM_REMOTE_LDFLDA, sp [0], NULL);
+                               t1->data.fi.klass = klass;
+                               t1->data.fi.field = field;
+                       } else {
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
 
-                       t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
+                               if (klass->valuetype)
+                                       t1->data.i = field->offset - sizeof (MonoObject);
+                               else 
+                                       t1->data.i = field->offset;
+
+                               t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
+                       }
 
-                       if (!load_addr)
+                       if (!load_addr) 
                                t1 = ctree_create_load (cfg, field->type, t1, &svt, FALSE);
                        else
                                svt = VAL_POINTER;
@@ -1832,16 +2063,17 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        }
                        g_assert (field);
 
-                       t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
-                       if (klass->valuetype)
-                               t1->data.i = field->offset - sizeof (MonoObject);
-                       else 
-                               t1->data.i = field->offset;
-
-                       //printf ("VALUETYPE %d %d %d\n", klass->valuetype, field->offset, t1->data.i);
+                       if (klass->marshalbyref) {
+                               t1 = mono_ctree_new (mp, map_remote_stind_type (field->type), sp [0], sp [1]);
+                               t1->data.fi.klass = klass;
+                               t1->data.fi.field = field;
+                       } else {
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t1->data.i = klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset;
+                               t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
+                               t1 = ctree_create_store (cfg, field->type, t1, sp [1], FALSE);
+                       }
 
-                       t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
-                       t1 = ctree_create_store (cfg, field->type, t1, sp [1], FALSE);
 
                        ADD_TREE (t1, cli_addr);
                        break;
@@ -1879,7 +2111,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        break;
                } 
                case CEE_SWITCH: {
-                       guint32 i, n;
+                       guint32 k, n;
                        MonoBBlock **jt;
                        gint32 st, target;
 
@@ -1897,8 +2129,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        create_outstack (cfg, bb, stack, sp - stack);
 
-                       for (i = 1; i <= (n + 1); i++) {
-                               if (i > n)
+                       for (k = 1; k <= (n + 1); k++) {
+                               if (k > n)
                                        target = st;
                                else {
                                        target = read32 (ip) + st;
@@ -1908,7 +2140,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                g_assert (bcinfo [target].is_block_start);
                                tbb = &cfg->bblocks [bcinfo [target].block_id];
                                mark_reached (cfg, tbb, stack, sp - stack);
-                               jt [i] = tbb; 
+                               jt [k] = tbb; 
                        }
 
                        ADD_TREE (t1, cli_addr);
@@ -1961,11 +2193,10 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                }
                case CEE_NEWOBJ: {
                        MonoMethodSignature *csig;
-                       MethodCallInfo *ci;
                        MonoMethod *cm;
                        MBTree *this = NULL;
                        guint32 token;
-                       int i, align, size, args_size = 0;
+                       int k, align, size, args_size = 0;
                        int newarr = FALSE;
 
                        ++ip;
@@ -1976,9 +2207,6 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        g_assert (cm);
                        g_assert (!strcmp (cm->name, ".ctor"));
                        
-                       ci =  mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
-                       ci->m = cm;
-
                        csig = cm->signature;
                        g_assert (csig->call_convention == MONO_CALL_DEFAULT);
                        g_assert (csig->hasthis);
@@ -2010,17 +2238,16 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        
                        args_size += sizeof (gpointer); /* this argument */             
 
-                       for (i = csig->param_count - 1; i >= 0; i--) {
-                               MonoType *type = cm->signature->params [i];
+                       for (k = csig->param_count - 1; k >= 0; k--) {
+                               MonoType *type = cm->signature->params [k];
 
                                size = mono_type_stack_size (type, &align);
-                               t1 = mono_ctree_new (mp, map_arg_type (type, FALSE), arg_sp [i], NULL); 
+                               t1 = mono_ctree_new (mp, map_arg_type (type), arg_sp [k], NULL);        
                                t1->data.i = size;
                                ADD_TREE (t1, cli_addr);
                                args_size += size;
                        }
 
-                       ci->args_size = args_size;
 
                        if (newarr) {
 
@@ -2028,7 +2255,10 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                t2->data.p = mono_array_new_va;
 
                                t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
-                               t1->data.p = ci;
+                               t1->data.ci.m = cm;
+                               t1->data.ci.args_size = args_size;
+                               t1->data.ci.vtype_num = 0;
+                               
                                t1->svt = VAL_POINTER;
 
                                t1 = mono_store_tree (cfg, -1, t1, &t2);
@@ -2037,17 +2267,20 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                PUSH_TREE (t2, t2->svt);
 
                        } else {
-                               
+
                                t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
                                t2->data.p = arch_create_jit_trampoline (cm);
 
                                t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
-                               t1->data.p = ci;
+                               t1->data.ci.m = cm;
+                               t1->data.ci.args_size = args_size;
+                               t1->data.ci.vtype_num = 0;
                                t1->svt = svt;
 
-                               ADD_TREE (t1, cli_addr); 
-                               t1 = ctree_create_dup (mp, this);       
+                               ADD_TREE (t1, cli_addr);
 
+                               t1 = ctree_create_dup (mp, this);       
+                               
                                if (cm->klass->valuetype) {
                                        t2 = ctree_create_load (cfg, &cm->klass->byval_arg, t1, &svt, FALSE);
                                        PUSH_TREE (t2, svt);
@@ -2060,15 +2293,15 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                case CEE_CALL: 
                case CEE_CALLVIRT: {
                        MonoMethodSignature *csig;
-                       MethodCallInfo *ci;
-                       MonoMethod *cm;
+                       MonoMethod *cm, *im;
                        MBTree *this = NULL;
                        guint32 token;
-                       int i, align, size, args_size = 0;
+                       int k, align, size, args_size = 0;
                        int virtual = *ip == CEE_CALLVIRT;
                        gboolean array_set = FALSE;
                        gboolean array_get = FALSE;
-                       gboolean pinvoke = FALSE;
+                       /* fixme: compute this value */
+                       gboolean shared_to_unshared_call = FALSE;
                        int nargs, vtype_num = 0;
 
                        ++ip;
@@ -2078,32 +2311,61 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        cm = mono_get_method (image, token, NULL);
                        g_assert (cm);
 
-                       ci =  mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
-                       ci->m = cm;
-
-                       if (cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL) {
-                               if (!(cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
-                                       pinvoke = TRUE;
-
-                               t1 = mono_ctree_new_leaf (mp, MB_TERM_SAVE_LMF);
-                               t1->data.m = cm;
-                               ADD_TREE (t1, cli_addr);
-                       }
+                       arg_sp = sp -= cm->signature->param_count;
 
                        if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
                            !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                virtual = 0;
 
+#ifdef INLINE_CALLS
+                       if (!virtual) {
+                               MBTree **sp1 = sp;
+
+                               if (cm->signature->hasthis)
+                                       sp1--;
+
+                               while (!virtual && 
+                                      (im = check_inlining (cfg, cm, &virtual, sp1, maxstack - (sp1 - stack)))) {
+                                       cm = im;
+                                       /*
+                                       printf ("INLINING %s.%s:%s %s.%s:%s\n", method->klass->name_space, 
+                                               method->klass->name, method->name, cm->klass->name_space,
+                                               cm->klass->name, cm->name);     
+                                       */
+                               }
+                       }
+#endif
                        csig = cm->signature;
+                       nargs = csig->param_count;
                        g_assert (csig->call_convention == MONO_CALL_DEFAULT);
                        g_assert (!virtual || csig->hasthis);
 
                        /* fixme: we need to unbox the this pointer for value types ?*/
                        g_assert (!virtual || !cm->klass->valuetype);
 
-                       nargs = csig->param_count;
-                       arg_sp = sp -= nargs;
-                       
+#ifdef INLINE_CALLS
+                       if (!virtual && csig->ret->type == MONO_TYPE_VOID &&
+                           !(cm->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) &&
+                           !(cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
+                           !(cm->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
+                           !cm->klass->marshalbyref) {
+                               MonoMethodHeader *mh = ((MonoMethodNormal *)cm)->header;
+                               
+                               if (mh && 
+                                   ((mh->code_size == 1 && mh->code [0] == CEE_RET) ||
+                                    (mh->code_size == 2 && mh->code [0] == CEE_NOP && 
+                                     mh->code [1] == CEE_RET))) {
+                                       //static int c = 0;
+
+                                       if (csig->hasthis)
+                                               sp--;
+
+                                       //printf ("C %s.%s:%s %d\n", cm->klass->name_space, cm->klass->name, cm->name, c++);
+                                       break;
+                               }
+                       }
+#endif
+
                        if (cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
                                if (cm->klass->parent == mono_defaults.array_class) {
                                        if (!strcmp (cm->name, "Set")) { 
@@ -2114,9 +2376,9 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                }
                        }
 
-                       for (i = nargs - 1; i >= 0; i--) {
-                               MonoType *type = cm->signature->params [i];
-                               t1 = mono_ctree_new (mp, map_arg_type (type, pinvoke), arg_sp [i], NULL);
+                       for (k = nargs - 1; k >= 0; k--) {
+                               MonoType *type = cm->signature->params [k];
+                               t1 = mono_ctree_new (mp, map_arg_type (type), arg_sp [k], NULL);
                                size = mono_type_stack_size (type, &align);
                                t1->data.i = size;
                                ADD_TREE (t1, cli_addr);
@@ -2131,23 +2393,21 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
 
                        if (ISSTRUCT (csig->ret)) {
-                               int size, align;
                                size = mono_type_size (csig->ret, &align);
                                vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
                        }
 
-                       ci->args_size = args_size;
-                       ci->vtype_num = vtype_num;
-
                        if (array_get) {
-                               int size, align, vnum;
+                               int vnum;
                                
                                t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
                                t2->data.p = ves_array_element_address;
 
                                t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
-                               t1->data.p = ci;
-
+                               t1->data.ci.m = cm;
+                               t1->data.ci.args_size = args_size;
+                               t1->data.ci.vtype_num = vtype_num;
                                t1 = mono_ctree_new (mp, map_ldind_type (csig->ret, &svt), t1, NULL);
                                t1->svt = svt;          
 
@@ -2169,14 +2429,18 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                t2->data.p = ves_array_element_address;
 
                                t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
-                               t1->data.p = ci;
+                               t1->data.ci.m = cm;
+                               t1->data.ci.args_size = args_size;
+                               t1->data.ci.vtype_num = vtype_num;
 
                                t1 = ctree_create_store (cfg, csig->params [nargs], t1, arg_sp [nargs], FALSE);
                                ADD_TREE (t1, cli_addr);
                        
                        } else {
 
-                               if (virtual) {
+                               if (virtual || (csig->hasthis && (cm->klass->marshalbyref || 
+                                                                 shared_to_unshared_call ||
+                                                                 cm->klass == mono_defaults.object_class))) {
                                        mono_class_init (cm->klass);
                                        
                                        if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
@@ -2187,13 +2451,14 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                        t2->data.m = cm;
 
                                } else {
-                       
                                        t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
                                        t2->data.p = arch_create_jit_trampoline (cm);
                                }
 
                                t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
-                               t1->data.p = ci;
+                               t1->data.ci.m = cm;
+                               t1->data.ci.args_size = args_size;
+                               t1->data.ci.vtype_num = vtype_num;
                                t1->svt = svt;
 
                                if (csig->ret->type != MONO_TYPE_VOID) {
@@ -2207,11 +2472,6 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                                t1 = mono_store_tree (cfg, -1, t1, &t2);
                                                g_assert (t1);
                                                ADD_TREE (t1, cli_addr);
-
-                                               if (pinvoke && csig->ret->type == MONO_TYPE_STRING) {
-                                                       t2 = mono_ctree_new (mp, MB_TERM_TOSTRING, t2, NULL);
-                                                       t2->svt = VAL_POINTER;
-                                               } 
                                                PUSH_TREE (t2, t2->svt);
                                        }
                                } else
@@ -2219,11 +2479,6 @@ mono_analyze_stack (MonoFlowGraph *cfg)
    
                        }
 
-                       if (cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL) {
-                               t1 = mono_ctree_new_leaf (mp, MB_TERM_RESTORE_LMF);
-                               ADD_TREE (t1, cli_addr);
-                       }
-
                        break;
                }
                case CEE_ISINST: {
@@ -2234,6 +2489,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        --sp;
 
                        c = mono_class_get (image, token);
+                       if (!c->inited)
+                               mono_class_init (c);
 
                        t1 = mono_ctree_new (mp, MB_TERM_ISINST, *sp, NULL);
                        t1->data.klass = c;
@@ -2251,6 +2508,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        --sp;
 
                        c = mono_class_get (image, token);
+                       if (!c->inited)
+                               mono_class_init (c);
 
                        t1 = mono_ctree_new (mp, MB_TERM_CASTCLASS, *sp, NULL);
                        t1->data.klass = c;
@@ -2263,7 +2522,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                case CEE_LDC_I4_S: { 
                        ++ip;
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
-                       t1->data.i = *(gint8 *)ip;
+                       t1->data.i = *(const gint8 *)ip;
                        ++ip;
                        PUSH_TREE (t1, VAL_I32);
                        break;
@@ -2337,7 +2596,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t1->data.i = LOCAL_POS (n);
-                       t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
+                       if (!ISSTRUCT (LOCAL_TYPE (n))) 
+                               t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
 
                        PUSH_TREE (t1, svt);
                        break;
@@ -2347,7 +2607,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t1->data.i = LOCAL_POS (*ip);
-                       t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt, FALSE);
+                       if (!ISSTRUCT (LOCAL_TYPE (*ip))) 
+                               t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt, FALSE);
                        ++ip;
 
                        PUSH_TREE (t1, svt);
@@ -2542,7 +2803,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                t1 = mono_ctree_new_leaf (mp, MB_TERM_HANDLER);
                                t1->data.p = hb;
                                ADD_TREE (t1, cli_addr);
-                       }
+                       } 
 
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
                        t1->data.p = tbb;
@@ -2669,7 +2930,9 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t1->data.i = ARG_POS (n);
-                       t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
+                       if (!ISSTRUCT (ARG_TYPE (n))) 
+                               t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
+                       
                        PUSH_TREE (t1, svt);
                        break;
                }
@@ -2678,7 +2941,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t1->data.i = ARG_POS (*ip);
-                       t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt, TRUE);
+                       if (!ISSTRUCT (ARG_TYPE (*ip))) 
+                               t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt, TRUE);
                        PUSH_TREE (t1, svt);
                        ++ip;
                        break;
@@ -2786,6 +3050,13 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        PUSH_TREE (t1, VAL_DOUBLE);             
                        break;
                }
+               case CEE_CONV_R_UN: {
+                       ++ip;
+                       sp--;
+                       t1 = mono_ctree_new (mp, MB_TERM_CONV_R_UN, *sp, NULL);
+                       PUSH_TREE (t1, VAL_DOUBLE);             
+                       break;
+               }
                case CEE_CONV_OVF_I:
                case CEE_CONV_OVF_I4: {
                        ++ip;
@@ -2895,11 +3166,14 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        switch (*ip) {
                                
                        case CEE_LDLOC: {
+                               int n;
                                ++ip;
-                       
+                               n = read16 (ip);
+
                                t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
-                               t1->data.i = LOCAL_POS (read16 (ip));
-                               t1 = ctree_create_load (cfg, LOCAL_TYPE (read16 (ip)), t1, &svt, FALSE);
+                               t1->data.i = LOCAL_POS (n);
+                               if (!ISSTRUCT (LOCAL_TYPE (n))) 
+                                       t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
                                ip += 2;
 
                                PUSH_TREE (t1, svt);
@@ -2950,11 +3224,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                cm = mono_get_method (image, token, NULL);
                                g_assert (cm);
                                
-                               t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
-                               if (!cm->addr)
-                                       t1->data.p = arch_compile_method (cm);
-                               else 
-                                       t1->data.p = (char *)cm->addr;
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_LDFTN);
+                               t1->data.m = cm;
                                PUSH_TREE (t1, VAL_POINTER);
                                break;
                        }
@@ -2976,7 +3247,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                                t2->data.m = cm;
 
-                               t1 = mono_ctree_new (mp, MB_TERM_LDFTN, *sp, t2);
+                               t1 = mono_ctree_new (mp, MB_TERM_LDVIRTFTN, *sp, t2);
 
                                PUSH_TREE (t1, VAL_POINTER);
 
@@ -3006,7 +3277,8 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                                t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                                t1->data.i = ARG_POS (n);
-                               t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
+                               if (!ISSTRUCT (ARG_TYPE (n))) 
+                                       t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
                                PUSH_TREE (t1, svt);
                                break;
                        }
@@ -3042,7 +3314,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                }       
                default:
                        g_warning ("unknown instruction `%s' at IL_%04X", 
-                                  opcode_names [*ip], ip - header->code);
+                                  mono_opcode_names [*ip], ip - header->code);
                        if (mono_debug_handle) {
                                cfg->invalid = 1;
                                return;
@@ -3076,6 +3348,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                repeat_count++;
                //printf ("REPEAT %d\n", repeat);
+               mono_jit_stats.analyze_stack_repeat++;
 
 
        } while (repeat);
@@ -3097,54 +3370,6 @@ ves_array_get (MonoArray *this, ...)
        g_assert_not_reached ();
 }
        
-/**
- * mono_jit_assembly:
- * @assembly: reference to an assembly
- *
- * JIT compilation of all methods in the assembly. Prints debugging
- * information on stdout.
- */
-static void
-mono_jit_assembly (MonoAssembly *assembly)
-{
-       MonoImage *image = assembly->image;
-       MonoMethod *method;
-       MonoTableInfo *t = &image->tables [MONO_TABLE_METHOD];
-       int i;
-
-       for (i = 0; i < t->rows; i++) {
-
-               method = mono_get_method (image, 
-                                         (MONO_TABLE_METHOD << 24) | (i + 1), 
-                                         NULL);
-
-               printf ("\nMethod: %s\n\n", method->name);
-
-               if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
-                       printf ("ABSTARCT\n");
-               else
-                       arch_compile_method (method);
-
-       }
-
-}
-
-static gint32
-jit_exec_main (MonoMethod *method, MonoArray *args)
-{
-       gint32 (*mfunc) (MonoArray*);
-       gint32 res;
-
-       mfunc = arch_compile_method (method);
-
-       res = mfunc (args);
-
-       if (method->signature->ret->type == MONO_TYPE_VOID)
-               res = 0;
-       
-       return res;
-}
-
 /**
  * mono_jit_exec:
  * @assembly: reference to an assembly
@@ -3153,7 +3378,7 @@ jit_exec_main (MonoMethod *method, MonoArray *args)
  *
  * Start execution of a program.
  */
-static int 
+int 
 mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
 {
        MonoArray *args = NULL;
@@ -3169,41 +3394,27 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[
                args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
                for (i = 0; i < argc; ++i) {
                        MonoString *arg = mono_string_new (domain, argv [i]);
-                       mono_array_set (args, gpointer, i, mono_string_intern (arg));
+                       mono_array_set (args, gpointer, i, arg);
                }
        }
        
        return mono_runtime_exec_main (method, args);
 }
 
-static void
-usage (char *name)
-{
-       fprintf (stderr,
-                "%s %s, the Mono ECMA CLI JIT Compiler, (C) 2001 Ximian, Inc.\n\n"
-                "Usage is: %s [options] executable args...\n", name,  VERSION, name);
-       fprintf (stderr,
-                "Valid Options are:\n"
-                "-d               debug the jit, show disassembler output.\n"
-                "--dump-asm       dumps the assembly code generated\n"
-                "--dump-forest    dumps the reconstructed forest\n"
-                "--trace-calls    printf function call trace\n"
-                "--share-code     force jit to produce shared code\n"
-                "--print-vtable   print the VTable of all used classes\n"
-                "--stabs          write stabs debug information\n"
-                "--compile cname  compile methods in given class (namespace.name[:methodname])\n"
-                "--ncompile num   compile methods num times (default: 1000)\n"
-                "--debug name     insert a breakpoint at the start of method name\n"
-                "--help           print this help message\n");
-       exit (1);
-}
+#ifdef PLATFORM_WIN32
+#define GET_CONTEXT \
+       struct sigcontext *ctx = (struct sigcontext*)_dummy;
+#else
+#define GET_CONTEXT \
+       void **_p = (void **)&_dummy; \
+       struct sigcontext *ctx = (struct sigcontext *)++_p;
+#endif
 
 static void
 sigfpe_signal_handler (int _dummy)
 {
        MonoException *exc;
-       void **_p = (void **)&_dummy;
-       struct sigcontext *ctx = (struct sigcontext *)++_p;
+       GET_CONTEXT
 
        exc = mono_get_exception_divide_by_zero ();
        
@@ -3216,10 +3427,9 @@ static void
 sigill_signal_handler (int _dummy)
 {
        MonoException *exc;
-       void **_p = (void **)&_dummy;
-       struct sigcontext *ctx = (struct sigcontext *)++_p;
+       GET_CONTEXT
 
-       exc = mono_get_exception_execution_engine ();
+       exc = mono_get_exception_execution_engine ("SIGILL");
        
        arch_handle_exception (ctx, exc);
 
@@ -3230,8 +3440,7 @@ static void
 sigsegv_signal_handler (int _dummy)
 {
        MonoException *exc;
-       void **_p = (void **)&_dummy;
-       struct sigcontext *ctx = (struct sigcontext *)++_p;
+       GET_CONTEXT
 
        exc = mono_get_exception_null_reference ();
        
@@ -3246,10 +3455,10 @@ sigsegv_signal_handler (int _dummy)
  *
  * abort the program, print exception information and stack trace
  */
-void
+static void
 mono_jit_abort (MonoObject *obj)
 {
-       char *message = "";
+       const char *message = "";
        char *trace = NULL;
        MonoString *str; ;
 
@@ -3273,63 +3482,22 @@ mono_jit_abort (MonoObject *obj)
        exit (1);
 }
 
-int 
-main (int argc, char *argv [])
-{
-       MonoDomain *domain;
-       struct sigaction sa;
-       MonoAssembly *assembly;
-       int retval = 0, i;
-       int compile_times = 1000;
-       char *compile_class = NULL;
-       char *file;
-       gboolean testjit = FALSE;
-       int stack, verbose = FALSE;
-
-       mono_end_of_stack = &stack; /* a pointer to a local variable is always < BP */
-
-       if (argc < 2)
-               usage (argv [0]);
-
-       for (i = 1; i < argc && argv [i][0] == '-'; i++){
-               if (strcmp (argv [i], "--help") == 0) {
-                       usage (argv [0]);
-               } else if (strcmp (argv [i], "-d") == 0) {
-                       testjit = TRUE;
-                       mono_jit_dump_asm = TRUE;
-                       mono_jit_dump_forest = TRUE;
-               } else if (strcmp (argv [i], "--dump-asm") == 0)
-                       mono_jit_dump_asm = TRUE;
-               else if (strcmp (argv [i], "--dump-forest") == 0)
-                       mono_jit_dump_forest = TRUE;
-               else if (strcmp (argv [i], "--trace-calls") == 0)
-                       mono_jit_trace_calls = TRUE;
-               else if (strcmp (argv [i], "--share-code") == 0)
-                       mono_jit_share_code = TRUE;
-               else if (strcmp (argv [i], "--print-vtable") == 0)
-                       mono_print_vtable = TRUE;
-               else if (strcmp (argv [i], "--debug") == 0) {
-                       mono_debug_methods = g_list_append (mono_debug_methods, argv [++i]);
-               } else if (strcmp (argv [i], "--count") == 0) {
-                       compile_times = atoi (argv [++i]);
-               } else if (strcmp (argv [i], "--compile") == 0) {
-                       compile_class = argv [++i];
-               } else if (strcmp (argv [i], "--ncompile") == 0) {
-                       compile_times = atoi (argv [++i]);
-               } else if (strcmp (argv [i], "--stabs") == 0) {
-                       mono_debug_handle = mono_debug_open_file ("");
-               } else if (strcmp (argv [i], "--verbose") == 0) {
-                       verbose = TRUE;;
-               } else
-                       usage (argv [0]);
-       }
-       
-       file = argv [i];
+static CRITICAL_SECTION ms;
 
-       if (!file)
-               usage (argv [0]);
+MonoDomain*
+mono_jit_init (char *file) {
+#ifndef PLATFORM_WIN32
+       struct sigaction sa;
+#endif
+       MonoDomain *domain;
 
 
+#ifdef PLATFORM_WIN32
+       win32_seh_init();
+       win32_seh_set_handler(SIGFPE, sigfpe_signal_handler);
+       win32_seh_set_handler(SIGILL, sigill_signal_handler);
+       win32_seh_set_handler(SIGSEGV, sigsegv_signal_handler);
+#else /* !PLATFORM_WIN32 */
        /* catch SIGFPE */
        sa.sa_handler = sigfpe_signal_handler;
        sigemptyset (&sa.sa_mask);
@@ -3342,104 +3510,83 @@ main (int argc, char *argv [])
        sa.sa_flags = 0;
        g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
 
+#if 1
        /* catch SIGSEGV */
        sa.sa_handler = sigsegv_signal_handler;
        sigemptyset (&sa.sa_mask);
        sa.sa_flags = 0;
-       //g_assert (syscall (SYS_sigaction, SIGSEGV, &sa, NULL) != -1);
+       g_assert (syscall (SYS_sigaction, SIGSEGV, &sa, NULL) != -1);
+#endif
+#endif /* PLATFORM_WIN32 */
 
        mono_init_icall ();
-       mono_add_internal_call ("__array_Set", ves_array_set);
-       mono_add_internal_call ("__array_Get", ves_array_get);
-       mono_add_internal_call ("__array_Address", ves_array_element_address);
+       mono_add_internal_call ("System.Array::Set", ves_array_set);
+       mono_add_internal_call ("System.Array::Get", ves_array_get);
+       mono_add_internal_call ("System.Array::Address", ves_array_element_address);
 
-       mono_jit_info_table = mono_jit_info_table_new ();
+       metadata_section = &ms;
+       InitializeCriticalSection (metadata_section);
 
        lmf_thread_id = TlsAlloc ();
        TlsSetValue (lmf_thread_id, NULL);
+       exc_cleanup_id = TlsAlloc ();
+       TlsSetValue (exc_cleanup_id, mono_jit_abort);
+       async_result_id = TlsAlloc ();
 
        mono_install_trampoline (arch_create_jit_trampoline);
-       mono_install_runtime_class_init (runtime_class_init);
-       mono_install_runtime_object_init (runtime_object_init);
-       mono_install_runtime_exec_main (jit_exec_main);
+       mono_install_remoting_trampoline (arch_create_remoting_trampoline);
        mono_install_handler (arch_get_throw_exception ());
+       mono_install_runtime_invoke (arch_runtime_invoke);
 
        domain = mono_init (file);
+       mono_runtime_init (domain);
        mono_thread_init (domain);
        mono_network_init ();
+       mono_delegate_init ();
 
-       assembly = mono_domain_assembly_open (domain, file);
-       if (!assembly){
-               fprintf (stderr, "Can not open image %s\n", file);
-               exit (1);
-       }
+       return domain;
+}
 
-       if (testjit) {
-               mono_jit_assembly (assembly);
-       } else if (compile_class) {
-               char *cmethod = strrchr (compile_class, ':');
-               char *cname;
-               char *code;
-               int i, j;
-               MonoClass *class;
-
-               if (cmethod)
-                       *cmethod++ = 0;
-               cname = strrchr (compile_class, '.');
-               if (cname)
-                       *cname++ = 0;
-               else {
-                       cname = compile_class;
-                       compile_class = "";
-               }
-               class = mono_class_from_name (assembly->image, compile_class, cname);
-               if (!class)
-                       g_error ("Cannot find class %s.%s", compile_class, cname);
-               mono_class_init (class);
-               if (cmethod) {
-                       MonoMethod *m = NULL;
-                       for (i = 0; i < class->method.count; ++i) {
-                               if (strcmp (class->methods [i]->name, cmethod) == 0) {
-                                       m = class->methods [i];
-                                       break;;
-                               }
-                       }
-                       if (!m)
-                               g_error ("Cannot find method %s.%s:%s", compile_class, cname, cmethod);
-                       for (j = 0; j < compile_times; ++j) {
-                               code = arch_compile_method (m);
-                               g_free (code);
-                       }
-               } else {
-                       for (j = 0; j < compile_times; ++j) {
-                               for (i = 0; i < class->method.count; ++i) {
-                                       if (class->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
-                                               continue;
-                                       if (class->methods [i]->flags & METHOD_ATTRIBUTE_ABSTRACT)
-                                               continue;
-                                       if (verbose)
-                                               g_print ("Compiling: %s\n", class->methods [i]->name);
-                                       code = arch_compile_method (class->methods [i]);
-                                       g_free (code);
-                               }
-                       }
-               }
-       } else {
-               /*
-                * skip the program name from the args.
-                */
-               ++i;
-               retval = mono_jit_exec (domain, assembly, argc - i, argv + i);
-               printf ("RESULT: %d\n", retval);
-       }
+void
+mono_jit_cleanup (MonoDomain *domain)
+{
+       if (mono_debug_handle)
+               mono_debug_close (mono_debug_handle);
+
+#ifdef PLATFORM_WIN32
+       win32_seh_cleanup();
+#endif
 
-       mono_network_cleanup();
-       mono_thread_cleanup();
+       mono_delegate_cleanup ();
+       mono_network_cleanup ();
+       mono_thread_cleanup ();
 
        mono_domain_unload (domain, TRUE);
 
-       return retval;
-}
+       if (mono_jit_stats.enabled) {
+               g_print ("Mono Jit statistics\n");
+               g_print ("Compiled methods:       %ld\n", mono_jit_stats.methods_compiled);
+               g_print ("Methods cache lookup:   %ld\n", mono_jit_stats.methods_lookups);
+               g_print ("Method trampolines:     %ld\n", mono_jit_stats.method_trampolines);
+               g_print ("Allocated vars:         %ld\n", mono_jit_stats.allocate_var);
+               g_print ("Analyze stack repeat:   %ld\n", mono_jit_stats.analyze_stack_repeat);
+               g_print ("Compiled CIL code size: %ld\n", mono_jit_stats.cil_code_size);
+               g_print ("Native code size:       %ld\n", mono_jit_stats.native_code_size);
+               g_print ("Max code size ratio:    %.2f (%s::%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
+                               mono_jit_stats.max_ratio_method->klass->name, mono_jit_stats.max_ratio_method->name);
+               g_print ("Biggest method:         %ld (%s::%s)\n", mono_jit_stats.biggest_method_size,
+                               mono_jit_stats.biggest_method->klass->name, mono_jit_stats.biggest_method->name);
+               g_print ("Code reallocs:          %ld\n", mono_jit_stats.code_reallocs);
+               g_print ("Allocated code size:    %ld\n", mono_jit_stats.allocated_code_size);
+
+               g_print ("\nCreated object count:   %ld\n", mono_stats.new_object_count);
+               g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
+               g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
+               g_print ("Static data size:       %ld\n", mono_stats.class_static_data_size);
+               g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
+       }
 
+       DeleteCriticalSection (metadata_section);
 
+}