[jit] Disable the optimization added by 63eb94e451a59491034516f2ec9f27d586b34d86...
[mono.git] / mono / mini / aot-compiler.c
old mode 100644 (file)
new mode 100755 (executable)
index 9ceb44c..6aef6f1
@@ -188,10 +188,12 @@ typedef struct MonoAotCompile {
        guint32 final_got_size;
        /* Number of GOT entries reserved for trampolines */
        guint32 num_trampoline_got_entries;
+       guint32 tramp_page_size;
 
        guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
        guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
+       guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
 
        MonoAotOptions aot_opts;
        guint32 nmethods;
@@ -233,6 +235,9 @@ typedef struct MonoAotCompile {
        GHashTable *dwarf_ln_filenames;
        gboolean global_symbols;
        gboolean direct_method_addresses;
+       int objc_selector_index, objc_selector_index_2;
+       GPtrArray *objc_selectors;
+       GHashTable *objc_selector_to_index;
 } MonoAotCompile;
 
 typedef struct {
@@ -637,6 +642,10 @@ arch_init (MonoAotCompile *acfg)
        g_string_append (acfg->llc_args, "-mattr=-avx");
 #endif
 
+#if defined(TARGET_AMD64)
+       g_string_append (acfg->llc_args, " -march=x86-64");
+#endif
+
 #ifdef TARGET_ARM
        if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "darwin")) {
                g_string_append (acfg->llc_args, "-mattr=+v6");
@@ -679,7 +688,7 @@ arch_init (MonoAotCompile *acfg)
  * calling code.
  */
 static void
-arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, int *call_size)
+arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, MonoJumpInfo *ji, int *call_size)
 {
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
        /* Need to make sure this is exactly 5 bytes long */
@@ -834,6 +843,35 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod
 
 #endif
 
+/*
+ * arch_emit_objc_selector_ref:
+ *
+ *   Emit the implementation of OP_OBJC_GET_SELECTOR, which itself implements @selector(foo:) in objective-c.
+ */
+static void
+arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size)
+{
+#if defined(TARGET_ARM)
+       char symbol1 [256];
+       char symbol2 [256];
+       int lindex = acfg->objc_selector_index_2 ++;
+
+       /* Emit ldr.imm/b */
+       emit_bytes (acfg, code, 8);
+
+       sprintf (symbol1, "L_OBJC_SELECTOR_%d", lindex);
+       sprintf (symbol2, "L_OBJC_SELECTOR_REFERENCES_%d", index);
+
+       emit_label (acfg, symbol1);
+       img_writer_emit_unset_mode (acfg->w);
+       fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
+
+       *code_size = 12;
+#else
+       g_assert_not_reached ();
+#endif
+}
+
 /*
  * arch_emit_plt_entry:
  *
@@ -998,6 +1036,8 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        if (!acfg->aot_opts.use_trampolines_page)
                return;
 
+       acfg->tramp_page_size = mono_pagesize ();
+
        sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
        emit_alignment (acfg, mono_pagesize ());
        emit_global (acfg, symbol, TRUE);
@@ -2668,8 +2708,11 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                                encode_klass_ref (acfg, method->klass, p, &p);
                        } else {
                                MonoMethodSignature *sig = mono_method_signature (method);
+                               WrapperInfo *info = mono_marshal_get_wrapper_info (method);
 
                                encode_value (0, p, &p);
+                               if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
+                                       encode_value (info ? info->subtype : 0, p, &p);
                                encode_signature (acfg, sig, p, &p);
                        }
                        break;
@@ -3162,8 +3205,6 @@ create_gsharedvt_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericCont
        }
 }
 
-#define MONO_TYPE_IS_PRIMITIVE(t) ((!(t)->byref && ((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))
-
 static void
 add_wrappers (MonoAotCompile *acfg)
 {
@@ -3303,10 +3344,6 @@ add_wrappers (MonoAotCompile *acfg)
                add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
 #endif
 
-               /* JIT icall wrappers */
-               /* FIXME: locking */
-               g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
-
                /* stelemref */
                add_method (acfg, mono_marshal_get_stelemref ());
 
@@ -3370,6 +3407,10 @@ add_wrappers (MonoAotCompile *acfg)
                        }
                }
 #endif
+
+               /* JIT icall wrappers */
+               /* FIXME: locking */
+               g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
        }
 
        /* 
@@ -4003,6 +4044,8 @@ add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method)
                for (j = 0; j < header->num_locals; ++j)
                        if (header->locals [j]->type == MONO_TYPE_GENERICINST)
                                add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local");
+       } else {
+               mono_loader_clear_error ();
        }
 }
 
@@ -4493,8 +4536,8 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                        mono_debug_symfile_free_location (loc);
                }
 
-#ifdef MONO_ARCH_AOT_SUPPORTED
                skip = FALSE;
+#ifdef MONO_ARCH_AOT_SUPPORTED
                if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
                        start_index = pindex;
 
@@ -4510,6 +4553,30 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                patch_info->type = MONO_PATCH_INFO_NONE;
                                break;
                        }
+                       case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
+                               int code_size, index;
+                               char *selector = (void*)patch_info->data.target;
+
+                               if (!acfg->objc_selector_to_index)
+                                       acfg->objc_selector_to_index = g_hash_table_new (g_str_hash, g_str_equal);
+                               if (!acfg->objc_selectors)
+                                       acfg->objc_selectors = g_ptr_array_new ();
+                               index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->objc_selector_to_index, selector));
+                               if (index)
+                                       index --;
+                               else {
+                                       index = acfg->objc_selector_index;
+                                       g_ptr_array_add (acfg->objc_selectors, (void*)patch_info->data.target);
+                                       g_hash_table_insert (acfg->objc_selector_to_index, selector, GUINT_TO_POINTER (index + 1));
+                                       acfg->objc_selector_index ++;
+                               }
+
+                               arch_emit_objc_selector_ref (acfg, code + i, index, &code_size);
+                               i += code_size - 1;
+                               skip = TRUE;
+                               patch_info->type = MONO_PATCH_INFO_NONE;
+                               break;
+                       }
                        default: {
                                /*
                                 * If this patch is a call, try emitting a direct call instead of
@@ -4583,7 +4650,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                if (direct_call) {
                                        int call_size;
 
-                                       arch_emit_direct_call (acfg, direct_call_target, external_call, &call_size);
+                                       arch_emit_direct_call (acfg, direct_call_target, external_call, patch_info, &call_size);
                                        i += call_size - 1;
                                } else {
                                        int code_size;
@@ -4746,7 +4813,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
        acfg->cfgs [method_index]->got_offset = acfg->got_offset;
 
-       emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
+       emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
 
        emit_line (acfg);
 
@@ -5206,8 +5273,18 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                                encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
                        else {
                                if (ei->data.catch_class) {
-                                       encode_value (1, p, &p);
-                                       encode_klass_ref (acfg, ei->data.catch_class, p, &p);
+                                       guint8 *buf2, *p2;
+                                       int len;
+
+                                       buf2 = g_malloc (4096);
+                                       p2 = buf2;
+                                       encode_klass_ref (acfg, ei->data.catch_class, p2, &p2);
+                                       len = p2 - buf2;
+                                       g_assert (len < 4096);
+                                       encode_value (len, p, &p);
+                                       memcpy (p, buf2, len);
+                                       p += p2 - buf2;
+                                       g_free (buf2);
                                } else {
                                        encode_value (0, p, &p);
                                }
@@ -5219,10 +5296,29 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
        }
 
+       if (jinfo->has_try_block_holes) {
+               MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
+               for (i = 0; i < table->num_holes; ++i) {
+                       MonoTryBlockHoleJitInfo *hole = &table->holes [i];
+                       encode_value (hole->clause, p, &p);
+                       encode_value (hole->length, p, &p);
+                       encode_value (hole->offset, p, &p);
+               }
+       }
+
+       if (jinfo->has_arch_eh_info) {
+               MonoArchEHJitInfo *eh_info;
+
+               eh_info = mono_jit_info_get_arch_eh_info (jinfo);
+               encode_value (eh_info->stack_size, p, &p);
+       }
+
        if (jinfo->has_generic_jit_info) {
                MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
                MonoGenericSharingContext* gsctx = gi->generic_sharing_context;
                guint8 *p1;
+               guint8 *buf2, *p2;
+               int len;
 
                p1 = p;
                encode_value (gi->nlocs, p, &p);
@@ -5252,15 +5348,23 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                 * Need to encode jinfo->method too, since it is not equal to 'method'
                 * when using generic sharing.
                 */
-               encode_method_ref (acfg, jinfo->method, p, &p);
+               buf2 = g_malloc (4096);
+               p2 = buf2;
+               encode_method_ref (acfg, jinfo->d.method, p2, &p2);
+               len = p2 - buf2;
+               g_assert (len < 4096);
+               encode_value (len, p, &p);
+               memcpy (p, buf2, len);
+               p += p2 - buf2;
+               g_free (buf2);
 
                if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
                        MonoMethodInflated *inflated;
                        MonoGenericContext *context;
                        MonoGenericInst *inst;
 
-                       g_assert (jinfo->method->is_inflated);
-                       inflated = (MonoMethodInflated*)jinfo->method;
+                       g_assert (jinfo->d.method->is_inflated);
+                       inflated = (MonoMethodInflated*)jinfo->d.method;
                        context = &inflated->context;
 
                        encode_value (1, p, &p);
@@ -5287,23 +5391,6 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
        }
 
-       if (jinfo->has_try_block_holes) {
-               MonoTryBlockHoleTableJitInfo *table = mono_jit_info_get_try_block_hole_table_info (jinfo);
-               for (i = 0; i < table->num_holes; ++i) {
-                       MonoTryBlockHoleJitInfo *hole = &table->holes [i];
-                       encode_value (hole->clause, p, &p);
-                       encode_value (hole->length, p, &p);
-                       encode_value (hole->offset, p, &p);
-               }
-       }
-
-       if (jinfo->has_arch_eh_info) {
-               MonoArchEHJitInfo *eh_info;
-
-               eh_info = mono_jit_info_get_arch_eh_info (jinfo);
-               encode_value (eh_info->stack_size, p, &p);
-       }
-
        if (seq_points) {
                int il_offset, native_offset, last_il_offset, last_native_offset, j;
 
@@ -5318,6 +5405,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        last_il_offset = il_offset;
                        last_native_offset = native_offset;
 
+                       encode_value (sp->flags, p, &p);
                        encode_value (sp->next_len, p, &p);
                        for (j = 0; j < sp->next_len; ++j)
                                encode_value (sp->next [j], p, &p);
@@ -5650,6 +5738,8 @@ emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info,
        MonoJumpInfo *ji;
        GSList *unwind_ops;
 
+       g_assert (info);
+
        name = info->name;
        code = info->code;
        code_size = info->code_size;
@@ -5964,6 +6054,7 @@ emit_trampolines (MonoAotCompile *acfg)
                        }
 
                        emit_label (acfg, end_symbol);
+                       emit_int32 (acfg, 0);
                }
 
                arch_emit_specific_trampoline_pages (acfg);
@@ -7116,6 +7207,7 @@ emit_code (MonoAotCompile *acfg)
        }
        sprintf (symbol, "unbox_trampolines_end");
        emit_label (acfg, symbol);
+       emit_int32 (acfg, 0);
 }
 
 static void
@@ -8038,6 +8130,9 @@ emit_file_info (MonoAotCompile *acfg)
        emit_int32 (acfg, __alignof__ (gint64));
 #endif
        emit_int32 (acfg, MONO_TRAMPOLINE_NUM);
+       emit_int32 (acfg, acfg->tramp_page_size);
+       for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+               emit_int32 (acfg, acfg->tramp_page_code_offsets [i]);
 
        if (acfg->aot_opts.static_link) {
                char *p;
@@ -8057,6 +8152,7 @@ emit_file_info (MonoAotCompile *acfg)
                }
                acfg->static_linking_symbol = g_strdup (symbol);
                emit_global_inner (acfg, symbol, FALSE);
+               emit_alignment (acfg, sizeof (gpointer));
                emit_label (acfg, symbol);
                emit_pointer_2 (acfg, acfg->user_symbol_prefix, "mono_aot_file_info");
        }
@@ -8075,6 +8171,45 @@ emit_blob (MonoAotCompile *acfg)
        emit_bytes (acfg, (guint8*)acfg->blob.data, acfg->blob.index);
 }
 
+static void
+emit_objc_selectors (MonoAotCompile *acfg)
+{
+       int i;
+
+       if (!acfg->objc_selectors || acfg->objc_selectors->len == 0)
+               return;
+
+       /*
+        * From
+        * cat > foo.m << EOF
+        * void *ret ()
+        * {
+        * return @selector(print:);
+        * }
+        * EOF
+        */
+
+       img_writer_emit_unset_mode (acfg->w);
+       g_assert (acfg->fp);
+       fprintf (acfg->fp, ".section    __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n");
+       fprintf (acfg->fp, ".align      2\n");
+       for (i = 0; i < acfg->objc_selectors->len; ++i) {
+               fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i);
+               fprintf (acfg->fp, ".long       L_OBJC_METH_VAR_NAME_%d\n", i);
+       }
+       fprintf (acfg->fp, ".section    __TEXT,__cstring,cstring_literals\n");
+       for (i = 0; i < acfg->objc_selectors->len; ++i) {
+               fprintf (acfg->fp, "L_OBJC_METH_VAR_NAME_%d:\n", i);
+               fprintf (acfg->fp, ".asciz \"%s\"\n", (char*)g_ptr_array_index (acfg->objc_selectors, i));
+       }
+
+       fprintf (acfg->fp, ".section    __DATA,__objc_imageinfo,regular,no_dead_strip\n");
+       fprintf (acfg->fp, ".align      2\n");
+       fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n");
+       fprintf (acfg->fp, ".long       0\n");
+       fprintf (acfg->fp, ".long       16\n");
+}
+
 static void
 emit_dwarf_info (MonoAotCompile *acfg)
 {
@@ -8095,7 +8230,7 @@ emit_dwarf_info (MonoAotCompile *acfg)
 
                sprintf (symbol2, "%sme_%x", acfg->temp_prefix, i);
 
-               mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->method, mono_domain_get ()));
+               mono_dwarf_writer_emit_method (acfg->dwarf, cfg, cfg->method, cfg->asm_symbol, symbol2, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, mono_debug_find_method (cfg->jit_info->d.method, mono_domain_get ()));
        }
 #endif
 }
@@ -8324,7 +8459,7 @@ compile_asm (MonoAotCompile *acfg)
 #elif defined(TARGET_AMD64) && defined(TARGET_MACH)
        command = g_strdup_printf ("gcc --shared -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #elif defined(HOST_WIN32)
-       command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
+       command = g_strdup_printf ("gcc -shared --dll -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
        command = g_strdup_printf ("gcc -m32 -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
 #else
@@ -8481,7 +8616,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        TV_DECLARE (atv);
        TV_DECLARE (btv);
 
-#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || !defined(MONO_EXTENSIONS)
+#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) || (!defined(MONO_EXTENSIONS) && !defined(MONOTOUCH))
        if (opts & MONO_OPT_GSHAREDVT) {
                fprintf (stderr, "-O=gsharedvt not supported on this platform.\n");
                exit (1);
@@ -8500,7 +8635,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        acfg->aot_opts.nrgctx_fetch_trampolines = 128;
        acfg->aot_opts.ngsharedvt_arg_trampolines = 128;
        acfg->aot_opts.llvm_path = g_strdup ("");
-#if MONOTOUCH
+#ifdef MONOTOUCH
        acfg->aot_opts.use_trampolines_page = TRUE;
 #endif
 
@@ -8696,10 +8831,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                                int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
                                acfg->fp = fdopen (i, "w+");
                        }
-                       if (acfg->fp == 0) {
-                               fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
-                               return 1;
-                       }
+               }
+               if (acfg->fp == 0) {
+                       fprintf (stderr, "Unable to open file '%s': %s\n", acfg->tmpfname, strerror (errno));
+                       return 1;
                }
                acfg->w = img_writer_create (acfg->fp, FALSE);
                
@@ -8787,6 +8922,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_blob (acfg);
 
+       emit_objc_selectors (acfg);
+
        emit_globals (acfg);
 
        emit_autoreg (acfg);