[llvmonly] Skip initalization of methods if they only reference shared got entries.
authorZoltan Varga <vargaz@gmail.com>
Wed, 14 Oct 2015 02:07:11 +0000 (22:07 -0400)
committerZoltan Varga <vargaz@gmail.com>
Wed, 14 Oct 2015 02:07:11 +0000 (22:07 -0400)
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/mini-codegen.c
mono/mini/mini-llvm.c
mono/mini/mini.h

index dd64cfdba8044ec83c7132dbefc22c8c0ff0a7a4..e54654aaeefc0cd7c0201ca573fe293800f0b18d 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;
@@ -7291,6 +7291,12 @@ mono_aot_get_got_offset (MonoJumpInfo *ji)
        return get_got_offset (llvm_acfg, TRUE, ji);
 }
 
+gboolean
+mono_aot_is_shared_got_offset (int offset)
+{
+       return offset < llvm_acfg->nshared_got_entries;
+}
+
 char*
 mono_aot_get_method_name (MonoCompile *cfg)
 {
@@ -9687,6 +9693,15 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                ji->data.name = "mono_aot_init_gshared_method_rgctx";
                get_got_offset (acfg, FALSE, ji);
                get_got_offset (acfg, TRUE, ji);
+
+               /* Slot 9 */
+               ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+               ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+               ji->data.name = "mono_llvm_throw_corlib_exception";
+               get_got_offset (acfg, FALSE, ji);
+               get_got_offset (acfg, TRUE, ji);
+
+               acfg->nshared_got_entries = acfg->got_offset;
        }
 
        TV_GETTIME (atv);
@@ -9925,4 +9940,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
index 470a417a655b4a668b8a749bf8f5e18554acfdb9..03dfcf172edd345d5bffc62910a6b5b937b0f546 100644 (file)
@@ -68,7 +68,7 @@
 #endif
 
 /* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 9
+#define N_COMMON_GOT_ENTRIES 10
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
@@ -1785,6 +1785,8 @@ init_amodule_got (MonoAotModule *amodule)
                amodule->shared_got [7] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
                ji.data.name = "mono_aot_init_gshared_method_rgctx";
                amodule->shared_got [8] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+               ji.data.name = "mono_llvm_throw_corlib_exception";
+               amodule->shared_got [9] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
                init_gots (amodule);
        }
 }
index c6efc5b78f864f67a42613376e6462921b8c9a02..a6fc7a4122f47c25cbf78e12224bd75c69ef454c 100644 (file)
@@ -437,6 +437,10 @@ mono_print_ji (const MonoJumpInfo *ji)
                g_free (s);
                break;
        }
+       case MONO_PATCH_INFO_INTERNAL_METHOD: {
+               printf ("[INTERNAL_METHOD - %s]", ji->data.name);
+               break;
+       }
        default:
                printf ("[%s]", patch_info_str [ji->type]);
                break;
index af70da0362780257079d163bf0bb629980c6a5a5..584da621ae0e8b1cbfcad6f5db40257fa49e6b85 100644 (file)
@@ -140,6 +140,7 @@ typedef struct {
        gboolean *is_dead;
        gboolean *unreachable;
        gboolean llvm_only;
+       gboolean has_got_access;
        int *pindexes;
        int this_arg_pindex, rgctx_arg_pindex;
        LLVMValueRef imt_rgctx_loc;
@@ -1505,6 +1506,15 @@ get_aotconst (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data)
 
        got_offset = mono_aot_get_got_offset (cfg->patch_info);
        ctx->lmodule->max_got_offset = MAX (ctx->lmodule->max_got_offset, got_offset);
+       /* 
+        * If the got slot is shared, it means its initialized when the aot image is loaded, so we don't need to
+        * explicitly initialize it.
+        */
+       if (!mono_aot_is_shared_got_offset (got_offset)) {
+               //mono_print_ji (ji);
+               //printf ("\n");
+               ctx->has_got_access = TRUE;
+       }
 
        indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
        indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
@@ -4661,6 +4671,11 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        //mono_add_patch_info (cfg, 0, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
                        got_offset = mono_aot_get_got_offset (cfg->patch_info);
                        ctx->lmodule->max_got_offset = MAX (ctx->lmodule->max_got_offset, got_offset);
+                       if (!mono_aot_is_shared_got_offset (got_offset)) {
+                               //mono_print_ji (ji);
+                               //printf ("\n");
+                               ctx->has_got_access = TRUE;
+                       }
  
                        indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
                        indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
@@ -6242,24 +6257,16 @@ mono_llvm_emit_method (MonoCompile *cfg)
 
        /* Initialize the method if needed */
        if (cfg->compile_aot && ctx->llvm_only) {
-               MonoJumpInfo *ji;
-               gboolean need_init = FALSE;
-
-               for (ji = cfg->patch_info; ji; ji = ji->next) {
-                       // FIXME: Pre-initialize slots for frequently used patches
-                       need_init = TRUE;
-               }
-
-               // FIXME: beforefieldinit
-               if (mono_class_get_cctor (cfg->method->klass))
-                       need_init = TRUE;
-
+               // FIXME: Add more shared got entries
                ctx->builder = create_builder (ctx);
                LLVMPositionBuilderAtEnd (ctx->builder, ctx->init_bb);
-               if (need_init)
+
+               // FIXME: beforefieldinit
+               if (ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) {
                        emit_init_method (ctx);
-               else
+               } else {
                        LLVMBuildBr (ctx->builder, ctx->inited_bb);
+               }
        }
 
        if (cfg->verbose_level > 1)
index 40f8719d6702537418cbc7747a0f1d2205dd900b..00ad3564dc687ad2dc44644c10952094e5eb2c19 100644 (file)
@@ -2325,6 +2325,7 @@ guint8*  mono_aot_get_unwind_info           (MonoJitInfo *ji, guint32 *unwind_in
 guint32  mono_aot_method_hash               (MonoMethod *method);
 MonoMethod* mono_aot_get_array_helper_from_wrapper (MonoMethod *method);
 guint32  mono_aot_get_got_offset            (MonoJumpInfo *ji) MONO_LLVM_INTERNAL;
+gboolean mono_aot_is_shared_got_offset      (int offset) MONO_LLVM_INTERNAL;
 char*    mono_aot_get_method_name           (MonoCompile *cfg) MONO_LLVM_INTERNAL;
 gboolean mono_aot_is_direct_callable        (MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
 void     mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;