2002-04-18 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / jit / jit.c
index 2caae6c86bf15ad4752e6237cf4371aefdb58115..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)
@@ -51,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)                                                      \
@@ -194,17 +188,37 @@ 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;
 
+/* 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;
+
+/* 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;
@@ -226,38 +240,6 @@ mono_alloc_static0 (int size)
 
 typedef void (*MonoCCtor) (void);
 
-/**
- * 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)
 {
@@ -331,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)
 {
@@ -927,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;
@@ -952,14 +989,14 @@ 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;
                }
        }       
@@ -982,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;
 }
@@ -1031,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)
 {
@@ -1120,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);
@@ -1155,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:
@@ -1304,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)
 
@@ -1402,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);
@@ -1507,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) {
@@ -1617,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;
                        }
@@ -1702,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;
@@ -1780,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;
@@ -1827,7 +2111,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        break;
                } 
                case CEE_SWITCH: {
-                       guint32 i, n;
+                       guint32 k, n;
                        MonoBBlock **jt;
                        gint32 st, target;
 
@@ -1845,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;
@@ -1856,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);
@@ -1909,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;
@@ -1924,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);
@@ -1958,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), 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) {
 
@@ -1976,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);
@@ -1985,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);
@@ -2008,14 +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;
+                       /* fixme: compute this value */
+                       gboolean shared_to_unshared_call = FALSE;
                        int nargs, vtype_num = 0;
 
                        ++ip;
@@ -2025,23 +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;
+                       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")) { 
@@ -2052,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), 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);
@@ -2069,22 +2393,20 @@ 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;          
@@ -2107,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)
@@ -2125,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) {
@@ -2162,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;
@@ -2179,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;
@@ -2191,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;
@@ -2893,8 +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);
-                               t1->data.p = arch_compile_method (cm);
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_LDFTN);
+                               t1->data.m = cm;
                                PUSH_TREE (t1, VAL_POINTER);
                                break;
                        }
@@ -2916,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);
 
@@ -2983,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;
@@ -3039,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
@@ -3095,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;
@@ -3111,43 +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"
-                "--dwarf          write dwarf2 debug information\n"
-                "--stats          print statistics about the jit operations\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 ();
        
@@ -3160,8 +3427,7 @@ 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 ("SIGILL");
        
@@ -3174,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 ();
        
@@ -3190,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; ;
 
@@ -3217,104 +3482,22 @@ mono_jit_abort (MonoObject *obj)
        exit (1);
 }
 
-#if HAVE_BOEHM_GC
-static void
-my_GC_free (void *p)
-{
-       /* do nothing */
-}
+static CRITICAL_SECTION ms;
 
-static void*
-my_GC_calloc (gsize n_blocks, gsize n_block_bytes)
-{
-       return GC_malloc (n_block_bytes * n_blocks);
-}
-#endif
-
-int 
-main (int argc, char *argv [])
-{
-       MonoDomain *domain;
+MonoDomain*
+mono_jit_init (char *file) {
+#ifndef PLATFORM_WIN32
        struct sigaction sa;
-       MonoAssembly *assembly;
-       int retval = 0, i;
-       int compile_times = 1000;
-       char *compile_class = NULL;
-       char *file, *error;
-       gboolean testjit = FALSE;
-       int stack, verbose = FALSE;
-       CRITICAL_SECTION ms;
-
-       mono_end_of_stack = &stack; /* a pointer to a local variable is always < BP */
-
-       if (argc < 2)
-               usage (argv [0]);
-
-#if HAVE_BOEHM_GC
-       {
-               static GMemVTable boehm_table = {
-                       GC_malloc,
-                       GC_realloc,
-                       my_GC_free,
-                       my_GC_calloc,
-                       GC_malloc, /* try variants */
-                       GC_realloc,
-               };
-               g_mem_set_vtable (&boehm_table);
-       }
 #endif
-
-       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) {
-                       MonoMethodDesc *desc = mono_method_desc_new (argv [++i], FALSE);
-                       if (!desc)
-                               g_error ("Invalid method name '%s'", argv [i]);
-                       mono_debug_methods = g_list_append (mono_debug_methods, desc);
-               } 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], "--stats") == 0) {
-                       memset (&mono_jit_stats, 0, sizeof (MonoJitStats));
-                       mono_jit_stats.enabled = TRUE;
-               } else if (strcmp (argv [i], "--stabs") == 0) {
-                       if (mono_debug_handle)
-                               g_error ("You can use either --stabs or --dwarf, but not both.");
-                       mono_debug_handle = mono_debug_open_file ("", MONO_DEBUG_FORMAT_STABS);
-               } else if (strcmp (argv [i], "--dwarf") == 0) {
-                       if (mono_debug_handle)
-                               g_error ("You can use either --stabs or --dwarf, but not both.");
-                       mono_debug_handle = mono_debug_open_file ("", MONO_DEBUG_FORMAT_DWARF2);
-               } else if (strcmp (argv [i], "--verbose") == 0) {
-                       verbose = TRUE;;
-               } else
-                       usage (argv [0]);
-       }
-       
-       file = argv [i];
-
-       if (!file)
-               usage (argv [0]);
+       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);
@@ -3327,109 +3510,53 @@ main (int argc, char *argv [])
        sa.sa_flags = 0;
        g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
 
-#ifndef HAVE_BOEHM_GC
+#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);
 
        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 ();
-
-       error = mono_verify_corlib ();
-       if (error) {
-               fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
-               exit (1);
-       }
-
        mono_delegate_init ();
 
-       assembly = mono_domain_assembly_open (domain, file);
-       if (!assembly){
-               fprintf (stderr, "Can not open image %s\n", file);
-               exit (1);
-       }
-
-       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) {
-                       MonoMethodDesc *mdesc;
-                       MonoMethod *m;
-                       mdesc = mono_method_desc_new (compile_class, FALSE);
-                       if (!mdesc)
-                               g_error ("Invalid method name '%s'", compile_class);
-                       m = mono_method_desc_search_in_image (mdesc, assembly->image);
-                       if (!m)
-                               g_error ("Cannot find method '%s'", compile_class);
-                       for (j = 0; j < compile_times; ++j) {
-                               code = arch_compile_method (m);
-                               g_free (code);
-                       }
-               } else {
-                       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);
-                       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);
-       }
+       return domain;
+}
 
+void
+mono_jit_cleanup (MonoDomain *domain)
+{
        if (mono_debug_handle)
                mono_debug_close (mono_debug_handle);
 
+#ifdef PLATFORM_WIN32
+       win32_seh_cleanup();
+#endif
+
        mono_delegate_cleanup ();
        mono_network_cleanup ();
        mono_thread_cleanup ();
@@ -3451,12 +3578,15 @@ main (int argc, char *argv [])
                                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);
 
-       return retval;
 }
 
-
-