[threads] Use runtime flag to enable cooperative suspend
[mono.git] / mono / mini / aot-compiler.c
index dd64cfdba8044ec83c7132dbefc22c8c0ff0a7a4..3eb775044a8182822cc9b7cce42d338133eff13f 100644 (file)
@@ -178,7 +178,7 @@ typedef struct MonoAotCompile {
        /* Maps MonoMethod* -> blob offset */
        GHashTable *method_blob_hash;
        guint32 *plt_got_info_offsets;
-       guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base;
+       guint32 got_offset, llvm_got_offset, plt_offset, plt_got_offset_base, nshared_got_entries;
        /* Number of GOT entries reserved for trampolines */
        guint32 num_trampoline_got_entries;
        guint32 tramp_page_size;
@@ -2518,20 +2518,9 @@ encode_klass_ref_inner (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, gui
                } else {
                        encode_value (par->gshared_constraint ? 1 : 0, p, &p);
                        if (par->gshared_constraint) {
-                               const char *name;
-
+                               MonoGSharedGenericParam *gpar = (MonoGSharedGenericParam*)par;
                                encode_type (acfg, par->gshared_constraint, p, &p);
-
-                               name = mono_generic_param_name (par);
-                               if (name) {
-                                       int len = strlen (name);
-
-                                       encode_value (len, p, &p);
-                                       memcpy (p, name, len);
-                                       p += len;
-                               } else {
-                                       encode_value (0, p, &p);
-                               }
+                               encode_klass_ref (acfg, mono_class_from_generic_parameter (gpar->parent, NULL, klass->byval_arg.type == MONO_TYPE_MVAR), p, &p);
                        }
                }
        } else if (klass->byval_arg.type == MONO_TYPE_PTR) {
@@ -7291,6 +7280,18 @@ mono_aot_get_got_offset (MonoJumpInfo *ji)
        return get_got_offset (llvm_acfg, TRUE, ji);
 }
 
+/*
+ * mono_aot_is_shared_got_offset:
+ *
+ *   Return whenever OFFSET refers to a GOT slot which is preinitialized
+ * when the AOT image is loaded.
+ */
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+       return offset < llvm_acfg->nshared_got_entries;
+}
+
 char*
 mono_aot_get_method_name (MonoCompile *cfg)
 {
@@ -7316,6 +7317,26 @@ mono_aot_mark_unused_llvm_plt_entry (MonoJumpInfo *patch_info)
        plt_entry->llvm_used = FALSE;
 }
 
+char*
+mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data)
+{
+       const char *sym = NULL;
+
+       if (llvm_acfg->aot_opts.direct_icalls) {
+               if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+                       /* Call to a C function implementing a jit icall */
+                       sym = mono_lookup_jit_icall_symbol (data);
+               } else if (type == MONO_PATCH_INFO_ICALL_ADDR) {
+                       MonoMethod *method = (gpointer)data;
+                       if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+                               sym = mono_lookup_icall_symbol (method);
+               }
+               if (sym)
+                       return g_strdup (sym);
+       }
+       return NULL;
+}
+
 char*
 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
 {
@@ -7411,6 +7432,11 @@ emit_llvm_file (MonoAotCompile *acfg)
        char *command, *opts, *tempbc, *output_fname;
 
        /* Emit the LLVM code into a .bc file */
+       if (acfg->aot_opts.llvm_only && acfg->aot_opts.asm_only) {
+               mono_llvm_emit_aot_module (acfg->aot_opts.llvm_outfile, g_path_get_basename (acfg->image->name));
+               return TRUE;
+       }
+
        tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
        mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name));
        g_free (tempbc);
@@ -8597,6 +8623,7 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info, int gc_name_off
        info->long_align = MONO_ABI_ALIGNOF (gint64);
        info->generic_tramp_num = MONO_TRAMPOLINE_NUM;
        info->tramp_page_size = acfg->tramp_page_size;
+       info->nshared_got_entries = acfg->nshared_got_entries;
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                info->tramp_page_code_offsets [i] = acfg->tramp_page_code_offsets [i];
 }
@@ -8712,6 +8739,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        emit_int32 (acfg, info->long_align);
        emit_int32 (acfg, info->generic_tramp_num);
        emit_int32 (acfg, info->tramp_page_size);
+       emit_int32 (acfg, info->nshared_got_entries);
 
        for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
                emit_int32 (acfg, info->num_trampolines [i]);
@@ -9455,6 +9483,68 @@ static void aot_dump (MonoAotCompile *acfg)
        mono_json_writer_destroy (&writer);
 }
 
+static const char *preinited_jit_icalls[] = {
+       "mono_aot_init_llvm_method",
+       "mono_aot_init_gshared_method_this",
+       "mono_aot_init_gshared_method_rgctx",
+       "mono_llvm_throw_corlib_exception",
+       "mono_resolve_vcall",
+       "mono_helper_ldstr_mscorlib"
+};
+
+static void
+add_preinit_got_slots (MonoAotCompile *acfg)
+{
+       MonoJumpInfo *ji;
+       int i;
+
+       /*
+        * Allocate the first few GOT entries to information which is needed frequently, or it is needed
+        * during method initialization etc.
+        */
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_IMAGE;
+       ji->data.image = acfg->image;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_AOT_MODULE;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
+       for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
+               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+               ji->data.name = preinited_jit_icalls [i];
+               get_got_offset (acfg, FALSE, ji);
+               get_got_offset (acfg, TRUE, ji);
+       }
+
+       acfg->nshared_got_entries = acfg->got_offset;
+}
+
 int
 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 {
@@ -9561,6 +9651,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (mono_aot_mode_is_full (&acfg->aot_opts))
                acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
 
+       if (mono_threads_is_coop_enabled ())
+               acfg->flags |= MONO_AOT_FILE_FLAG_SAFEPOINTS;
+
        if (acfg->aot_opts.instances_logfile_path) {
                acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
                if (!acfg->instances_logfile) {
@@ -9619,6 +9712,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        /* PLT offset 0 is reserved for the PLT trampoline */
        acfg->plt_offset = 1;
+       add_preinit_got_slots (acfg);
 
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
@@ -9627,68 +9721,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        }
 #endif
 
-       {
-               MonoJumpInfo *ji;
-
-               /* Slot 0 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_IMAGE;
-               ji->data.image = acfg->image;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 1 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 2 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 3 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 4 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 5 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
-               ji->type = MONO_PATCH_INFO_AOT_MODULE;
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 6 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
-               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
-               ji->data.name = "mono_aot_init_llvm_method";
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 7 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
-               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
-               ji->data.name = "mono_aot_init_gshared_method_this";
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-
-               /* Slot 8 */
-               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
-               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
-               ji->data.name = "mono_aot_init_gshared_method_rgctx";
-               get_got_offset (acfg, FALSE, ji);
-               get_got_offset (acfg, TRUE, ji);
-       }
-
        TV_GETTIME (atv);
 
        compile_methods (acfg);
@@ -9925,4 +9957,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        return 0;
 }
 
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+       return FALSE;
+}
+
 #endif