2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / interpreter / interp.c
index 3f7ad24660dc3e529a32260fc4fcb131cd0ea40d..214b1b14f61ad08d12ca0229a858820066865c2e 100644 (file)
@@ -233,12 +233,11 @@ static void
 ves_real_abort (int line, MonoMethod *mh,
                const unsigned short *ip, stackval *stack, stackval *sp)
 {
-       MonoMethodNormal *mm = (MonoMethodNormal *)mh;
        fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
        fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
-                ip-(const unsigned short *)mm->header->code);
+                ip-(const unsigned short *)mono_method_get_header (mh)->code);
        g_print ("0x%04x %02x\n",
-                ip-(const unsigned short *)mm->header->code, *ip);
+                ip-(const unsigned short *)mono_method_get_header (mh)->code, *ip);
        if (sp > stack)
                printf ("\t[%d] 0x%08x %0.5f\n", sp-stack, sp[-1].data.i, sp[-1].data.f);
 }
@@ -250,9 +249,9 @@ ves_real_abort (int line, MonoMethod *mh,
        } while (0);
 
 static gpointer
-interp_create_remoting_trampoline (MonoMethod *method)
+interp_create_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
 {
-       return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke (method));
+       return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke_for_target (method, target));
 }
 
 static CRITICAL_SECTION runtime_method_lookup_section;
@@ -271,8 +270,8 @@ mono_interp_get_runtime_method (MonoMethod *method)
        rtm = mono_mempool_alloc (domain->mp, sizeof (RuntimeMethod));
        memset (rtm, 0, sizeof (*rtm));
        rtm->method = method;
-       rtm->param_count = method->signature->param_count;
-       rtm->hasthis = method->signature->hasthis;
+       rtm->param_count = mono_method_signature (method)->param_count;
+       rtm->hasthis = mono_method_signature (method)->hasthis;
        rtm->valuetype = method->klass->valuetype;
        g_hash_table_insert (domain->jit_code_hash, method, rtm);
        LeaveCriticalSection (&runtime_method_lookup_section);
@@ -579,7 +578,7 @@ ves_array_set (MonoInvocation *frame)
        esize = mono_array_element_size (ac);
        ea = mono_array_addr_with_size (ao, esize, pos);
 
-       mt = frame->runtime_method->method->signature->params [ac->rank];
+       mt = mono_method_signature (frame->runtime_method->method)->params [ac->rank];
        stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
 }
 
@@ -623,7 +622,7 @@ ves_array_get (MonoInvocation *frame)
        esize = mono_array_element_size (ac);
        ea = mono_array_addr_with_size (ao, esize, pos);
 
-       mt = frame->runtime_method->method->signature->ret;
+       mt = mono_method_signature (frame->runtime_method->method)->ret;
        stackval_from_data (mt, frame->retval, ea, FALSE);
 }
 
@@ -669,13 +668,17 @@ ves_array_element_address (MonoInvocation *frame)
 }
 
 static void
-interp_walk_stack (MonoStackWalk func, gpointer user_data)
+interp_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data)
 {
        ThreadContext *context = TlsGetValue (thread_context_id);
-       MonoInvocation *frame = context->current_frame;
+       MonoInvocation *frame;
        int il_offset;
        MonoMethodHeader *hd;
 
+       if (!context) return;
+               
+       frame = context->current_frame;
+
        while (frame) {
                gboolean managed = FALSE;
                MonoMethod *method = frame->runtime_method->method;
@@ -683,7 +686,7 @@ interp_walk_stack (MonoStackWalk func, gpointer user_data)
                                (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
                        il_offset = -1;
                else {
-                       hd = ((MonoMethodNormal*)method)->header;
+                       hd = mono_method_get_header (method);
                        il_offset = frame->ip - (const unsigned short *)hd->code;
                        if (!method->wrapper_type)
                                managed = TRUE;
@@ -760,6 +763,25 @@ interp_delegate_ctor (MonoDomain *domain, MonoObject *this, MonoObject *target,
        }
 }
 
+MonoDelegate*
+mono_interp_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
+{
+       MonoDelegate *d;
+       MonoJitInfo *ji;
+       MonoDomain *domain = mono_domain_get ();
+
+       d = (MonoDelegate*)mono_object_new (domain, klass);
+
+       ji = mono_jit_info_table_find (domain, ftn);
+       if (ji == NULL)
+               mono_raise_exception (mono_get_exception_argument ("", "Function pointer was not created by a Delegate."));
+
+       /* FIXME: discard the wrapper and call the original method */
+       interp_delegate_ctor (domain, (MonoObject*)d, NULL, mono_interp_get_runtime_method (ji->method));
+
+       return d;
+}
+
 /*
  * From the spec:
  * runtime specifies that the implementation of the method is automatically
@@ -864,7 +886,7 @@ dump_args (MonoInvocation *inv)
 {
        GString *str = g_string_new ("");
        int i;
-       MonoMethodSignature *signature = inv->runtime_method->method->signature;
+       MonoMethodSignature *signature = mono_method_signature (inv->runtime_method->method);
        
        if (signature->param_count == 0)
                return g_string_free (str, FALSE);
@@ -882,7 +904,7 @@ static char*
 dump_retval (MonoInvocation *inv)
 {
        GString *str = g_string_new ("");
-       MonoType *ret = inv->runtime_method->method->signature->ret;
+       MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
 
        if (ret->type != MONO_TYPE_VOID)
                dump_stackval (str, inv->retval, ret);
@@ -910,7 +932,7 @@ dump_frame (MonoInvocation *inv)
 
                        if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
                                (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
-                               MonoMethodHeader *hd = ((MonoMethodNormal *)method)->header;
+                               MonoMethodHeader *hd = mono_method_get_header (method);
 
                                if (hd != NULL) {
                                        if (inv->ip) {
@@ -1049,7 +1071,7 @@ interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
        MonoInvocation frame;
        ThreadContext * volatile context = TlsGetValue (thread_context_id);
        MonoObject *retval = NULL;
-       MonoMethodSignature *sig = method->signature;
+       MonoMethodSignature *sig = mono_method_signature (method);
        MonoClass *klass = mono_class_from_mono_type (sig->ret);
        int i, type, isobject = 0;
        void *ret = NULL;
@@ -1164,10 +1186,6 @@ handle_enum:
                }
        }
 
-       if (method->klass->valuetype && obj)
-               /* Unbox the instance, since valuetype methods expect an interior pointer. */
-               obj = mono_object_unbox (obj);
-
        if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) 
                method = mono_marshal_get_native_wrapper (method);
        INIT_FRAME(&frame,context->current_frame,obj,args,&result,method);
@@ -1200,6 +1218,89 @@ handle_enum:
        return retval;
 }
 
+static stackval * 
+do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
+{
+       MonoInvocation *old_frame = context->current_frame;
+       MonoInvocation *old_env_frame = context->env_frame;
+       jmp_buf *old_env = context->current_env;
+       jmp_buf env;
+
+       if (setjmp (env)) {
+               context->current_frame = old_frame;
+               context->env_frame = old_env_frame;
+               context->current_env = old_env;
+               context->managed_code = 1;
+               return sp;
+       }
+
+       context->env_frame = context->current_frame;
+       context->current_env = &env;
+       context->managed_code = 0;
+
+       switch (op) {
+       case MINT_ICALL_V_V: {
+               void (*func)() = ptr;
+               func ();
+               break;
+       }
+       case MINT_ICALL_P_V: {
+               void (*func)(gpointer) = ptr;
+               func (sp [-1].data.p);
+               sp --;
+               break;
+       }
+       case MINT_ICALL_P_P: {
+               gpointer (*func)(gpointer) = ptr;
+               sp [-1].data.p = func (sp [-1].data.p);
+               break;
+       }
+       case MINT_ICALL_PP_V: {
+               void (*func)(gpointer,gpointer) = ptr;
+               sp -= 2;
+               func (sp [0].data.p, sp [1].data.p);
+               break;
+       }
+       case MINT_ICALL_PI_V: {
+               void (*func)(gpointer,int) = ptr;
+               sp -= 2;
+               func (sp [0].data.p, sp [1].data.i);
+               break;
+       }
+       case MINT_ICALL_PP_P: {
+               gpointer (*func)(gpointer,gpointer) = ptr;
+               --sp;
+               sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
+               break;
+       }
+       case MINT_ICALL_PI_P: {
+               gpointer (*func)(gpointer,int) = ptr;
+               --sp;
+               sp [-1].data.p = func (sp [-1].data.p, sp [0].data.i);
+               break;
+       }
+       case MINT_ICALL_PPP_V: {
+               void (*func)(gpointer,gpointer,gpointer) = ptr;
+               sp -= 3;
+               func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
+               break;
+       }
+       case MINT_ICALL_PPI_V: {
+               void (*func)(gpointer,gpointer,int) = ptr;
+               sp -= 3;
+               func (sp [0].data.p, sp [1].data.p, sp [2].data.i);
+               break;
+       }
+       default:
+               g_assert_not_reached ();
+       }
+
+       context->env_frame = old_env_frame;
+       context->current_env = old_env;
+
+       return sp;
+}
+
 static CRITICAL_SECTION create_method_pointer_mutex;
 
 static MonoGHashTable *method_pointer_hash = NULL;
@@ -1212,6 +1313,7 @@ mono_create_method_pointer (MonoMethod *method)
 
        EnterCriticalSection (&create_method_pointer_mutex);
        if (!method_pointer_hash) {
+               MONO_GC_REGISTER_ROOT (method_pointer_hash);
                method_pointer_hash = mono_g_hash_table_new (NULL, NULL);
        }
        addr = mono_g_hash_table_lookup (method_pointer_hash, method);
@@ -1224,15 +1326,13 @@ mono_create_method_pointer (MonoMethod *method)
         * If it is a static P/Invoke method, we can just return the pointer
         * to the method implementation.
         */
-       if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && method->addr) {
+       if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) {
                ji = g_new0 (MonoJitInfo, 1);
                ji->method = method;
                ji->code_size = 1;
-               ji->code_start = method->addr;
+               ji->code_start = addr = ((MonoMethodPInvoke*) method)->addr;
 
                mono_jit_info_table_add (mono_get_root_domain (), ji);
-               
-               addr = method->addr;
        }               
        else
                addr = mono_arch_create_method_pointer (method);
@@ -1282,7 +1382,7 @@ static int opcode_counts[512];
 #else
 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
 #endif
-#define MINT_IN_DEFAULT mint_default:
+#define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
 #else
 #define MINT_IN_SWITCH(op) switch (op)
 #define MINT_IN_CASE(x) case x:
@@ -1466,6 +1566,14 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        ++sp;
                        ++ip; 
                        MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_DUP_VT)
+                       i32 = READ32 (ip + 1);
+                       sp->data.p = vt_sp;
+                       memcpy(sp->data.p, sp [-1].data.p, i32);
+                       vt_sp += (i32 + 7) & ~7;
+                       ++sp;
+                       ip += 3;
+                       MINT_IN_BREAK;
                MINT_IN_CASE(MINT_POP)
                        ++ip;
                        --sp;
@@ -1755,7 +1863,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        MINT_IN_BREAK;
                }
                MINT_IN_CASE(MINT_CALLINT)
-                       ves_pinvoke_method (frame, frame->runtime_method->method->signature, frame->runtime_method->method->addr, 
+                       ves_pinvoke_method (frame, mono_method_signature (frame->runtime_method->method), ((MonoMethodPInvoke*) frame->runtime_method->method)->addr, 
                                    frame->runtime_method->method->string_ctor, context);
                        if (frame->ex) {
                                rtm = NULL;
@@ -2469,7 +2577,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        ip += 2;
 
                        child_frame.runtime_method = rtm->data_items [token];
-                       csig = child_frame.runtime_method->method->signature;
+                       csig = mono_method_signature (child_frame.runtime_method->method);
                        newobj_class = child_frame.runtime_method->method->klass;
                        /*if (profiling_classes) {
                                guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
@@ -3385,89 +3493,21 @@ array_constructed:
                        }
                        goto handle_finally;
                        MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_MONO_CONV1)
-                       ip += 2;
-                       switch (ip [-1]) {
-                       case MONO_MARSHAL_CONV_STR_LPWSTR:
-                               sp [-1].data.p = mono_string_to_utf16 (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_LPSTR_STR:
-                               sp [-1].data.p = mono_string_new_wrapper (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STR_LPTSTR:
-                       case MONO_MARSHAL_CONV_STR_LPSTR:
-                               sp [-1].data.p = mono_string_to_utf8 (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STR_BSTR:
-                               sp [-1].data.p = mono_string_to_bstr (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STR_TBSTR:
-                       case MONO_MARSHAL_CONV_STR_ANSIBSTR:
-                               sp [-1].data.p = mono_string_to_ansibstr (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_SB_LPSTR:
-                       case MONO_MARSHAL_CONV_SB_LPTSTR:
-                               sp [-1].data.p = mono_string_builder_to_utf8 (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_SB_LPWSTR:
-                               sp [-1].data.p = mono_string_builder_to_utf16 (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
-                               sp [-1].data.p = mono_array_to_savearray (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
-                               sp [-1].data.p = mono_array_to_lparray (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_DEL_FTN:
-                               sp [-1].data.p = mono_delegate_to_ftnptr (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
-                               sp [-1].data.p = mono_marshal_string_array (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY:
-                               sp [-1].data.p = mono_marshal_string_array_to_unicode (sp [-1].data.p);
-                               break;
-                       case MONO_MARSHAL_CONV_LPWSTR_STR:
-                               sp [-1].data.p = mono_string_from_utf16 (sp [-1].data.p);
-                               MINT_IN_BREAK;
-                       default:
-                               fprintf(stderr, "MINT_MONO_CONV1 %d", ip[-1]);
-                               g_assert_not_reached ();
-                       }
-                       MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_MONO_CONV2)
-                       sp -= 2;
-                       ip += 2;
-                       switch (ip [-1]) {
-                       case MONO_MARSHAL_CONV_LPSTR_SB:
-                       case MONO_MARSHAL_CONV_LPTSTR_SB:
-                               mono_string_utf8_to_builder (sp [0].data.p, sp [1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_LPWSTR_SB:
-                               mono_string_utf16_to_builder (sp [0].data.p, sp [1].data.p);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_FREE_ARRAY:
-                               mono_marshal_free_array (sp [0].data.p, sp [1].data.i);
-                               MINT_IN_BREAK;
-                       default:
-                               g_assert_not_reached ();
-                       }                                
-                       MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_MONO_CONV3)
-                       sp -= 3;
+               MINT_IN_CASE(MINT_ICALL_V_V) 
+               MINT_IN_CASE(MINT_ICALL_P_V) 
+               MINT_IN_CASE(MINT_ICALL_P_P)
+               MINT_IN_CASE(MINT_ICALL_PP_V)
+               MINT_IN_CASE(MINT_ICALL_PI_V)
+               MINT_IN_CASE(MINT_ICALL_PP_P)
+               MINT_IN_CASE(MINT_ICALL_PI_P)
+               MINT_IN_CASE(MINT_ICALL_PPP_V)
+               MINT_IN_CASE(MINT_ICALL_PPI_V)
+                       sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
+                       if (frame->ex != NULL)
+                               goto handle_exception;
                        ip += 2;
-                       switch (ip [-1]) {
-                       case MONO_MARSHAL_CONV_STR_BYVALSTR:
-                               mono_string_to_byvalstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
-                               MINT_IN_BREAK;
-                       case MONO_MARSHAL_CONV_STR_BYVALWSTR:
-                               mono_string_to_byvalwstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
-                               MINT_IN_BREAK;
-                       default:
-                               g_assert_not_reached ();
-                       }
                        MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_MONO_LDPTR)
+               MINT_IN_CASE(MINT_MONO_LDPTR) 
                        sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
                        ip += 2;
                        ++sp;
@@ -3485,7 +3525,8 @@ array_constructed:
                MINT_IN_CASE(MINT_MONO_RETOBJ)
                        ++ip;
                        sp--;
-                       stackval_from_data (frame->runtime_method->method->signature->ret, frame->retval, sp->data.p, frame->runtime_method->method->signature->pinvoke);
+                       stackval_from_data (mono_method_signature frame->runtime_method->method)->ret, frame->retval, sp->data.p,
+                            mono_method_signature (frame->runtime_method->method)->pinvoke);
                        if (sp > frame->stack)
                                g_warning ("retobj: more values on stack: %d", sp-frame->stack);
                        goto exit_frame;
@@ -3858,7 +3899,7 @@ array_constructed:
                                clause = &inv->runtime_method->clauses [i];
                                if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
                                        if (!clause->flags) {
-                                               if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (method->klass->image, clause->token_or_filter))) {
+                                               if (mono_object_isinst ((MonoObject*)frame->ex, clause->data.catch_class)) {
                                                        /* 
                                                         * OK, we found an handler, now we need to execute the finally
                                                         * and fault blocks before branching to the handler code.
@@ -3896,7 +3937,7 @@ die_on_ex:
                MonoExceptionClause *clause;
                GSList *old_list = finally_ips;
                MonoMethod *method = frame->runtime_method->method;
-               MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
+               MonoMethodHeader *header = mono_method_get_header (method);
                
 #if DEBUG_INTERP
                if (tracing)
@@ -3950,7 +3991,7 @@ die_on_ex:
                int i;
                guint32 ip_offset;
                MonoExceptionClause *clause;
-               MonoMethodHeader *header = ((MonoMethodNormal *)frame->runtime_method->method)->header;
+               MonoMethodHeader *header = mono_method_get_header (frame->runtime_method->method);
                
 #if DEBUG_INTERP
                if (tracing)
@@ -4159,7 +4200,6 @@ static void
 thread_abort_handler (int signum)
 {
        ThreadContext *context = TlsGetValue (thread_context_id);
-       MonoThread *thread;
        MonoException *exc;
 
        if (context == NULL)
@@ -4280,8 +4320,10 @@ static void main_thread_handler (gpointer user_data)
        MainThreadArgs *main_args=(MainThreadArgs *)user_data;
        MonoAssembly *assembly;
 
-       if (main_args->enable_debugging)
-               mono_debug_init (main_args->domain, MONO_DEBUG_FORMAT_MONO);
+       if (main_args->enable_debugging) {
+               mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+               mono_debug_init_1 (main_args->domain);
+       }
 
        assembly = mono_domain_assembly_open (main_args->domain,
                                              main_args->file);
@@ -4344,7 +4386,8 @@ mono_interp_init(const char *file)
        g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
        g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
 
-       g_thread_init (NULL);
+       if (!g_thread_supported ())
+               g_thread_init (NULL);
 
        thread_context_id = TlsAlloc ();
        TlsSetValue (thread_context_id, NULL);
@@ -4360,21 +4403,25 @@ mono_interp_init(const char *file)
 
        mono_install_handler (interp_ex_handler);
        mono_install_stack_walk (interp_walk_stack);
-       mono_runtime_install_cleanup (quit_function);
+       mono_install_runtime_cleanup (quit_function);
        abort_requested = mono_thread_interruption_request_flag ();
 
-       domain = mono_init (file);
+       domain = mono_init_from_assembly (file, file);
 #ifdef __hpux /* generates very big stack frames */
        mono_threads_set_default_stacksize(32*1024*1024);
 #endif
-       mono_init_icall ();
+       mono_icall_init ();
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", ves_icall_get_frame_info);
        mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", ves_icall_get_trace);
        mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
        mono_add_internal_call ("System.Delegate::CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal);
 
+       mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", mono_create_icall_signature ("void"), FALSE);
+
        mono_runtime_init (domain, NULL, NULL);
 
+
+       mono_thread_attach (domain);
        return domain;
 }
 
@@ -4392,6 +4439,8 @@ mono_main (int argc, char *argv [])
        if (argc < 2)
                usage ();
 
+       MONO_GC_PRE_INIT ();
+       
        for (i = 1; i < argc && argv [i][0] == '-'; i++){
                if (strcmp (argv [i], "--trace") == 0)
                        global_tracing = 1;