Don't use System.Environment.Exit to finish a sdb session on iOS.
[mono.git] / mono / mini / mini-x86.c
index cd5d97ce2f4cef7b0eaa43fc43e0600ef9dfbbca..f562ea7f5ad924c8a10714f185c3227ccc5e1020 100644 (file)
@@ -582,7 +582,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
  * FIXME: The metadata calls might not be signal safe.
  */
 int
-mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
+mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
 {
        int len, k, args_size = 0;
        int size, pad;
@@ -595,7 +595,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
        cinfo = (CallInfo*)g_newa (guint8*, len);
        memset (cinfo, 0, len);
 
-       cinfo = get_call_info_internal (NULL, cinfo, csig);
+       cinfo = get_call_info_internal (gsctx, cinfo, csig);
 
        arg_info [0].offset = offset;
 
@@ -801,6 +801,10 @@ mono_arch_init (void)
 void
 mono_arch_cleanup (void)
 {
+       if (ss_trigger_page)
+               mono_vfree (ss_trigger_page, mono_pagesize ());
+       if (bp_trigger_page)
+               mono_vfree (bp_trigger_page, mono_pagesize ());
        DeleteCriticalSection (&mini_arch_mutex);
 }
 
@@ -808,7 +812,7 @@ mono_arch_cleanup (void)
  * This function returns the optimizations supported on this cpu.
  */
 guint32
-mono_arch_cpu_optimizazions (guint32 *exclude_mask)
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
 {
 #if !defined(__native_client__)
        int eax, ebx, ecx, edx;
@@ -1245,6 +1249,8 @@ mono_arch_create_vars (MonoCompile *cfg)
        if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig->ret)) {
                cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
        }
+
+       cfg->arch_eh_jit_info = 1;
 }
 
 /*
@@ -1278,9 +1284,7 @@ static void
 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
 {
        MonoMethodSignature *tmp_sig;
-
-       /* FIXME: Add support for signature tokens to AOT */
-       cfg->disable_aot = TRUE;
+       int sig_reg;
 
        /*
         * mono_ArgIterator_Setup assumes the signature cookie is 
@@ -1293,7 +1297,13 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
        tmp_sig->sentinelpos = 0;
        memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
 
-       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig);
+       if (cfg->compile_aot) {
+               sig_reg = mono_alloc_ireg (cfg);
+               MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig);
+               MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, sig_reg);
+       } else {
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig);
+       }
 }
 
 #ifdef ENABLE_LLVM
@@ -1475,7 +1485,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
        /* Arguments are pushed in the reverse order */
        for (i = n - 1; i >= 0; i --) {
                ArgInfo *ainfo = cinfo->args + i;
-               MonoType *t;
+               MonoType *orig_type, *t;
                int argsize;
 
                if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && i == 0) {
@@ -1493,6 +1503,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        t = sig->params [i - sig->hasthis];
                else
                        t = &mono_defaults.int_class->byval_arg;
+               orig_type = t;
                t = mini_type_get_underlying_type (cfg->generic_sharing_context, t);
 
                MONO_INST_NEW (cfg, arg, OP_X86_PUSH);
@@ -1526,7 +1537,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
 
                                MONO_ADD_INS (cfg->cbb, arg);
                                sp_offset += size;
-                               emit_gc_param_slot_def (cfg, sp_offset, t);
+                               emit_gc_param_slot_def (cfg, sp_offset, orig_type);
                        }
                } else {
                        argsize = 4;
@@ -1565,11 +1576,16 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        if (cfg->compute_gc_maps) {
                                if (argsize == 4) {
                                        /* FIXME: The == STACK_OBJ check might be fragile ? */
-                                       if (sig->hasthis && i == 0 && call->args [i]->type == STACK_OBJ)
+                                       if (sig->hasthis && i == 0 && call->args [i]->type == STACK_OBJ) {
                                                /* this */
-                                               emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg);
-                                       else
-                                               emit_gc_param_slot_def (cfg, sp_offset, t);
+                                               if (call->need_unbox_trampoline)
+                                                       /* The unbox trampoline transforms this into a managed pointer */
+                                                       emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.int_class->this_arg);
+                                               else
+                                                       emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg);
+                                       } else {
+                                               emit_gc_param_slot_def (cfg, sp_offset, orig_type);
+                                       }
                                } else {
                                        /* i8/r8 */
                                        for (j = 0; j < argsize; j += 4)
@@ -1617,6 +1633,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
        }
 
        call->stack_usage = cinfo->stack_usage;
+       call->stack_align_amount = cinfo->stack_align_amount;
        cfg->arch.param_area_size = MAX (cfg->arch.param_area_size, sp_offset);
 }
 
@@ -2275,11 +2292,12 @@ mono_x86_have_tls_get (void)
 #ifdef __APPLE__
        static gboolean have_tls_get = FALSE;
        static gboolean inited = FALSE;
+       guint32 *ins;
 
        if (inited)
                return have_tls_get;
 
-       guint32 *ins = (guint32*)pthread_getspecific;
+       ins = (guint32*)pthread_getspecific;
        /*
         * We're looking for these two instructions:
         *
@@ -2292,11 +2310,28 @@ mono_x86_have_tls_get (void)
        inited = TRUE;
 
        return have_tls_get;
+#elif defined(TARGET_ANDROID)
+       return FALSE;
 #else
        return TRUE;
 #endif
 }
 
+static guint8*
+mono_x86_emit_tls_set (guint8* code, int sreg, int tls_offset)
+{
+#if defined(__APPLE__)
+       x86_prefix (code, X86_GS_PREFIX);
+       x86_mov_mem_reg (code, tls_gs_offset + (tls_offset * 4), sreg, 4);
+#elif defined(TARGET_WIN32)
+       g_assert_not_reached ();
+#else
+       x86_prefix (code, X86_GS_PREFIX);
+       x86_mov_mem_reg (code, tls_offset, sreg, 4);
+#endif
+       return code;
+}
+
 /*
  * mono_x86_emit_tls_get:
  * @code: buffer to store code to
@@ -2703,6 +2738,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                         */
                        for (i = 0; i < 6; ++i)
                                x86_nop (code);
+                       /*
+                        * Add an additional nop so skipping the bp doesn't cause the ip to point
+                        * to another IL offset.
+                        */
+                       x86_nop (code);
                        break;
                }
                case OP_ADDCC:
@@ -3146,7 +3186,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
 
                        /* Copy arguments on the stack to our argument area */
-                       for (i = 0; i < call->stack_usage; i += 4) {
+                       for (i = 0; i < call->stack_usage - call->stack_align_amount; i += 4) {
                                x86_mov_reg_membase (code, X86_EAX, X86_ESP, i, 4);
                                x86_mov_membase_reg (code, X86_EBP, 8 + i, X86_EAX, 4);
                        }
@@ -3157,6 +3197,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
                        x86_jump32 (code, 0);
 
+                       ins->flags |= MONO_INST_GC_CALLSITE;
                        cfg->disable_aot = TRUE;
                        break;
                }
@@ -5020,49 +5061,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        alloc_size = cfg->stack_offset;
        pos = 0;
 
-       if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
-               /* Might need to attach the thread to the JIT  or change the domain for the callback */
-               if (appdomain_tls_offset != -1 && lmf_tls_offset != -1) {
-                       guint8 *buf, *no_domain_branch;
-
-                       code = mono_x86_emit_tls_get (code, X86_EAX, appdomain_tls_offset);
-                       x86_alu_reg_imm (code, X86_CMP, X86_EAX, GPOINTER_TO_UINT (cfg->domain));
-                       no_domain_branch = code;
-                       x86_branch8 (code, X86_CC_NE, 0, 0);
-                       code = mono_x86_emit_tls_get ( code, X86_EAX, lmf_tls_offset);
-                       x86_test_reg_reg (code, X86_EAX, X86_EAX);
-                       buf = code;
-                       x86_branch8 (code, X86_CC_NE, 0, 0);
-                       x86_patch (no_domain_branch, code);
-                       x86_push_imm (code, cfg->domain);
-                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
-                       x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
-                       x86_patch (buf, code);
-#ifdef TARGET_WIN32
-                       /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
-                       /* FIXME: Add a separate key for LMF to avoid this */
-                       x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
-#endif
-               }
-               else {
-                       if (cfg->compile_aot) {
-                               /* 
-                                * This goes before the saving of callee saved regs, so save the got reg
-                                * ourselves.
-                                */
-                               x86_push_reg (code, MONO_ARCH_GOT_REG);
-                               code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
-                               x86_push_imm (code, 0);
-                       } else {
-                               x86_push_imm (code, cfg->domain);
-                       }
-                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
-                       x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
-                       if (cfg->compile_aot)
-                               x86_pop_reg (code, MONO_ARCH_GOT_REG);
-               }
-       }
-
        if (method->save_lmf) {
                pos += sizeof (MonoLMF);
 
@@ -5100,8 +5098,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                         * through the mono_lmf_addr TLS variable.
                         */
                        /* %eax = previous_lmf */
-                       x86_prefix (code, X86_GS_PREFIX);
-                       x86_mov_reg_mem (code, X86_EAX, lmf_tls_offset, 4);
+                       code = mono_x86_emit_tls_get (code, X86_EAX, lmf_tls_offset);
                        /* skip esp + method_info + lmf */
                        x86_alu_reg_imm (code, X86_SUB, X86_ESP, 12);
                        cfa_offset += 12;
@@ -5113,8 +5110,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        cfa_offset += 4;
                        mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
                        /* new lmf = ESP */
-                       x86_prefix (code, X86_GS_PREFIX);
-                       x86_mov_mem_reg (code, lmf_tls_offset, X86_ESP, 4);
+                       code = mono_x86_emit_tls_set (code, X86_ESP, lmf_tls_offset);
                } else {
                        /* get the address of lmf for the current thread */
                        /* 
@@ -5360,8 +5356,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                        x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
 
                        /* lmf = previous_lmf */
-                       x86_prefix (code, X86_GS_PREFIX);
-                       x86_mov_mem_reg (code, lmf_tls_offset, X86_ECX, 4);
+                       code = mono_x86_emit_tls_set (code, X86_ECX, lmf_tls_offset);
                } else {
                        /* Find a spare register */
                        switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
@@ -5453,7 +5448,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        if (CALLCONV_IS_STDCALL (sig)) {
                MonoJitArgumentInfo *arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
 
-               stack_to_pop = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+               stack_to_pop = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
        } else if (MONO_TYPE_ISSTRUCT (mono_method_signature (cfg->method)->ret) && (cinfo->ret.storage == ArgOnStack))
                stack_to_pop = 4;
        else
@@ -5600,41 +5595,31 @@ mono_arch_is_inst_imm (gint64 imm)
        return TRUE;
 }
 
-/*
- * Support for fast access to the thread-local lmf structure using the GS
- * segment register on NPTL + kernel 2.6.x.
- */
-
-static gboolean tls_offset_inited = FALSE;
-
 void
-mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
+mono_arch_finish_init (void)
 {
-       if (!tls_offset_inited) {
-               if (!getenv ("MONO_NO_TLS")) {
+       if (!getenv ("MONO_NO_TLS")) {
 #ifdef TARGET_WIN32
-                       /* 
-                        * We need to init this multiple times, since when we are first called, the key might not
-                        * be initialized yet.
-                        */
-                       appdomain_tls_offset = mono_domain_get_tls_key ();
-                       lmf_tls_offset = mono_get_jit_tls_key ();
-
-                       /* Only 64 tls entries can be accessed using inline code */
-                       if (appdomain_tls_offset >= 64)
-                               appdomain_tls_offset = -1;
-                       if (lmf_tls_offset >= 64)
-                               lmf_tls_offset = -1;
+               /* 
+                * We need to init this multiple times, since when we are first called, the key might not
+                * be initialized yet.
+                */
+               appdomain_tls_offset = mono_domain_get_tls_key ();
+               lmf_tls_offset = mono_get_jit_tls_key ();
+
+               /* Only 64 tls entries can be accessed using inline code */
+               if (appdomain_tls_offset >= 64)
+                       appdomain_tls_offset = -1;
+               if (lmf_tls_offset >= 64)
+                       lmf_tls_offset = -1;
 #else
 #if MONO_XEN_OPT
-                       optimize_for_xen = access ("/proc/xen", F_OK) == 0;
+               optimize_for_xen = access ("/proc/xen", F_OK) == 0;
 #endif
-                       tls_offset_inited = TRUE;
-                       appdomain_tls_offset = mono_domain_get_tls_offset ();
-                       lmf_tls_offset = mono_get_lmf_tls_offset ();
-                       lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
+               appdomain_tls_offset = mono_domain_get_tls_offset ();
+               lmf_tls_offset = mono_get_lmf_tls_offset ();
+               lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
 #endif
-               }
        }               
 }
 
@@ -6625,44 +6610,15 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx)
 #endif
 }
 
-/*
- * mono_arch_get_ip_for_breakpoint:
- *
- *   See mini-amd64.c for docs.
- */
-guint8*
-mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx)
-{
-       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
-
-       return ip;
-}
-
 #define BREAKPOINT_SIZE 6
 
-/*
- * mono_arch_get_ip_for_single_step:
- *
- *   See mini-amd64.c for docs.
- */
-guint8*
-mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx)
-{
-       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
-
-       /* Size of x86_alu_reg_imm */
-       ip += 6;
-
-       return ip;
-}
-
 /*
  * mono_arch_skip_breakpoint:
  *
  *   See mini-amd64.c for docs.
  */
 void
-mono_arch_skip_breakpoint (MonoContext *ctx)
+mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
 {
        MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
 }