[llvm] Define a separate symbol for the aot method info for every method. Pass this...
authormonojenkins <jo.shields+jenkins@xamarin.com>
Mon, 6 Apr 2020 22:14:07 +0000 (18:14 -0400)
committerGitHub <noreply@github.com>
Mon, 6 Apr 2020 22:14:07 +0000 (18:14 -0400)
This removes a dependency the generated code has on the method index, hopefully allowing separate compilation etc. in the future.

<!--
Thank you for your Pull Request!

If you are new to contributing to Mono, please try to do your best at conforming to our coding guidelines http://www.mono-project.com/community/contributing/coding-guidelines/ but don't worry if you get something wrong. One of the project members will help you to get things landed.

Does your pull request fix any of the existing issues? Please use the following format: Fixes #issue-number
-->

Co-authored-by: vargaz <vargaz@users.noreply.github.com>
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/aot-runtime.c
src/mono/mono/mini/aot-runtime.h
src/mono/mono/mini/llvmonly-runtime.c
src/mono/mono/mini/llvmonly-runtime.h
src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-llvm.h
src/mono/mono/mini/mini-runtime.c
src/mono/mono/mini/mini.c
src/mono/mono/mini/mini.h

index 768a009..a83aa8b 100644 (file)
@@ -6865,7 +6865,10 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                flags |= MONO_AOT_METHOD_FLAG_HAS_PATCHES;
        if (needs_ctx && ctx)
                flags |= MONO_AOT_METHOD_FLAG_HAS_CTX;
-       encode_value (flags, p, &p);
+       /* Saved into another table so it can be accessed without having access to this data */
+       cfg->aot_method_flags = flags;
+
+       encode_int (cfg->method_index, p, &p);
        if (flags & MONO_AOT_METHOD_FLAG_HAS_CCTOR)
                encode_klass_ref (acfg, method->klass, p, &p);
        if (needs_ctx && ctx)
@@ -6884,7 +6887,15 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        g_assert (p - buf < buf_size);
 
-       cfg->method_info_offset = add_to_blob (acfg, buf, p - buf);
+       if (cfg->compile_llvm) {
+               char *symbol = g_strdup_printf ("info_%s", cfg->llvm_method_name);
+               cfg->llvm_info_var = mono_llvm_emit_aot_data_aligned (symbol, buf, p - buf, 1);
+               g_free (symbol);
+               /* aot-runtime.c will use this to check whenever this is an llvm method */
+               cfg->method_info_offset = 0;
+       } else {
+               cfg->method_info_offset = add_to_blob (acfg, buf, p - buf);
+       }
        g_free (buf);
 }
 
@@ -10356,10 +10367,11 @@ emit_code (MonoAotCompile *acfg)
 }
 
 static void
-emit_info (MonoAotCompile *acfg)
+emit_method_info_table (MonoAotCompile *acfg)
 {
        int oindex, i;
        gint32 *offsets;
+       guint8 *method_flags;
 
        offsets = g_new0 (gint32, acfg->nmethods);
 
@@ -10377,6 +10389,14 @@ emit_info (MonoAotCompile *acfg)
        acfg->stats.offsets_size += emit_offset_table (acfg, "method_info_offsets", MONO_AOT_TABLE_METHOD_INFO_OFFSETS, acfg->nmethods, 10, offsets);
 
        g_free (offsets);
+
+       /* Emit a separate table for method flags, its needed at runtime */
+       method_flags = g_new0 (guint8, acfg->nmethods);
+       for (i = 0; i < acfg->nmethods; ++i) {
+               if (acfg->cfgs [i])
+                       method_flags [acfg->cfgs [i]->method_index] = acfg->cfgs [i]->aot_method_flags;
+       }
+       emit_aot_data (acfg, MONO_AOT_TABLE_FLAGS_TABLE, "method_flags_table", method_flags, acfg->nmethods);
 }
 
 #endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
@@ -11397,6 +11417,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
                        symbols [sindex ++] = NULL;
                symbols [sindex ++] = "image_table";
                symbols [sindex ++] = "weak_field_indexes";
+               symbols [sindex ++] = "method_flags_table";
        }
 
        symbols [sindex ++] = "mem_end";
@@ -14161,7 +14182,7 @@ emit_aot_image (MonoAotCompile *acfg)
 
        emit_code (acfg);
 
-       emit_info (acfg);
+       emit_method_info_table (acfg);
 
        emit_extra_methods (acfg);
 
index 97423e4..43dda8c 100644 (file)
@@ -250,7 +250,7 @@ static void
 compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end);
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoError *error);
+init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoError *error);
 
 static MonoJumpInfo*
 decode_patches (MonoAotModule *amodule, MonoMemPool *mp, int n_patches, gboolean llvm, guint32 *got_offsets);
@@ -4321,9 +4321,12 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
 
        if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) ||
                (mono_llvm_only && method && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
-               res = init_method (amodule, method_index, method, NULL, error);
-               if (!res)
-                       goto cleanup;
+               /* offset == 0 means its llvm code */
+               if (mono_aot_get_offset (amodule->method_info_offsets, method_index) != 0) {
+                       res = init_method (amodule, NULL, method_index, method, NULL, error);
+                       if (!res)
+                               goto cleanup;
+               }
        }
 
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
@@ -4345,11 +4348,7 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
        }
 
        if (mono_llvm_only) {
-               guint8 *info, *p;
-
-               info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
-               p = info;
-               guint8 flags = decode_value (p, &p);
+               guint8 flags = amodule->info.method_flags_table [method_index];
                /* The caller needs to looks this up, but its hard to do without constructing the full MonoJitInfo, so save it here */
                if (flags & MONO_AOT_METHOD_FLAG_GSHAREDVT_VARIABLE) {
                        mono_aot_lock ();
@@ -4600,7 +4599,7 @@ mono_aot_find_method_index (MonoMethod *method)
 }
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoError *error)
+init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoError *error)
 {
        MonoDomain *domain = mono_domain_get ();
        MonoMemPool *mp;
@@ -4609,7 +4608,7 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        int pindex, n_patches;
        guint8 *p;
        MonoJitInfo *jinfo = NULL;
-       guint8 *code, *info;
+       guint8 *code;
        MonoGenericContext *context;
        MonoGenericContext ctx;
 
@@ -4621,12 +4620,21 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
 
        error_init (error);
 
-       code = (guint8 *)amodule->methods [method_index];
-       info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
+       if (!info)
+               info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
 
-       p = info;
+       p = (guint8*)info;
+
+       // FIXME: Is this aligned ?
+       guint32 encoded_method_index = *(guint32*)p;
+       if (method_index)
+               g_assert (method_index == encoded_method_index);
+       method_index = encoded_method_index;
+       p += 4;
+
+       code = (guint8 *)amodule->methods [method_index];
+       guint8 flags = amodule->info.method_flags_table [method_index];
 
-       guint8 flags = decode_value (p, &p);
        if (flags & MONO_AOT_METHOD_FLAG_HAS_CCTOR)
                klass_to_run_ctor = decode_klass_ref (amodule, p, &p, error);
        if (!is_ok (error))
@@ -4756,17 +4764,16 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
 }
 
 /*
- * mono_aot_init_llvmonly_method:
+ * mono_aot_init_llvm_method:
  *
- *   Initialize the method identified by METHOD_INDEX in llvmonly mode.
+ *   Initialize the LLVM method identified by METHOD_INFO.
  */
 gboolean
-mono_aot_init_llvmonly_method (gpointer aot_module, guint32 method_index, MonoClass *init_class, MonoError *error)
+mono_aot_init_llvm_method (gpointer aot_module, gpointer method_info, MonoClass *init_class, MonoError *error)
 {
        MonoAotModule *amodule = (MonoAotModule*)aot_module;
-       MonoMethod *method = NULL;
 
-       return init_method (amodule, method_index, method, init_class, error);
+       return init_method (amodule, method_info, 0, NULL, init_class, error);
 }
 
 /*
index 91ea7ac..57dd480 100644 (file)
@@ -97,6 +97,7 @@ typedef enum {
        MONO_AOT_TABLE_EXTRA_METHOD_INFO_OFFSETS,
        MONO_AOT_TABLE_EXTRA_METHOD_TABLE,
        MONO_AOT_TABLE_WEAK_FIELD_INDEXES,
+       MONO_AOT_TABLE_FLAGS_TABLE,
        MONO_AOT_TABLE_NUM
 } MonoAotFileTable;
 
@@ -144,6 +145,7 @@ typedef struct MonoAotFileInfo
        gpointer image_table;
        /* Points to an array of weak field indexes */
        gpointer weak_field_indexes;
+       guint8 *method_flags_table;
 
        gpointer mem_end;
        /* The GUID of the assembly which the AOT image was generated from */
@@ -271,7 +273,7 @@ gboolean mono_aot_is_pagefault              (void *ptr);
 void     mono_aot_handle_pagefault          (void *ptr);
 
 guint32  mono_aot_find_method_index         (MonoMethod *method);
-gboolean mono_aot_init_llvmonly_method      (gpointer amodule, guint32 method_index, MonoClass *init_class, MonoError *error);
+gboolean mono_aot_init_llvm_method          (gpointer aot_module, gpointer method_info, MonoClass *init_class, MonoError *error);
 GHashTable *mono_aot_get_weak_field_indexes (MonoImage *image);
 MonoAotMethodFlags mono_aot_get_method_flags (guint8 *code);
 
index 3104e29..100cffb 100644 (file)
@@ -768,13 +768,16 @@ mini_llvmonly_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot,
        return res;
 }
 
-static void
-init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoClass *init_class)
+/* Called from LLVM code to initialize a method */
+// FIXME: This should be somewhere else
+void
+mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer method_info, MonoVTable *vtable)
 {
-       ERROR_DECL (error);
        gboolean res;
+       MonoAotModule *amodule = (MonoAotModule *)aot_module;
+       ERROR_DECL (error);
 
-       res = mono_aot_init_llvmonly_method (amodule, method_index, init_class, error);
+       res = mono_aot_init_llvm_method (amodule, method_info, vtable ? vtable->klass : NULL, error);
        if (!res || !is_ok (error)) {
                MonoException *ex = mono_error_convert_to_exception (error);
                if (ex) {
@@ -788,15 +791,6 @@ init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoClass *i
        }
 }
 
-/* Called from generated code to initialize a method */
-void
-mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoVTable *vtable)
-{
-       MonoAotModule *amodule = (MonoAotModule *)aot_module;
-
-       init_llvmonly_method (amodule, method_index, vtable ? vtable->klass : NULL);
-}
-
 static GENERATE_GET_CLASS_WITH_CACHE (nullref, "System", "NullReferenceException")
 
 void
index f939916..35aa4dc 100644 (file)
@@ -29,7 +29,7 @@ G_EXTERN_C void mini_llvmonly_init_delegate (MonoDelegate *del);
 G_EXTERN_C void mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method);
 
 /* Used for regular llvm as well */
-G_EXTERN_C void mini_llvm_init_method          (MonoAotFileInfo *info, gpointer aot_module, guint32 method_index, MonoVTable *vtable);
+G_EXTERN_C void mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer method_info, MonoVTable *vtable);
 
 G_EXTERN_C void mini_llvmonly_throw_nullref_exception (void);
 
index 25f58b7..4392f33 100644 (file)
@@ -3000,37 +3000,37 @@ emit_llvm_code_start (MonoLLVMModule *module)
 }
 
 /*
- * emit_init_icall_wrapper:
+ * emit_init_func:
  *
- *   Emit wrappers around the mini_llvm_init_method () JIT icall.
+ *   Emit functions to initialize LLVM methods.
+ * These are wrappers around the mini_llvm_init_method () JIT icall.
  * The wrappers handle adding the 'amodule' argument, loading the vtable from different locations, and they have
  * a cold calling convention.
  */
 static LLVMValueRef
-emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
+emit_init_func (MonoLLVMModule *module, MonoAotInitSubtype subtype)
 {
        LLVMModuleRef lmodule = module->lmodule;
-       LLVMValueRef func, indexes [2], args [16], callee, inited_var, cmp;
+       LLVMValueRef func, indexes [2], args [16], callee, info_var, index_var, inited_var, cmp;
        LLVMBasicBlockRef entry_bb, inited_bb, notinited_bb;
        LLVMBuilderRef builder;
        LLVMTypeRef icall_sig;
        const char *wrapper_name = mono_marshal_get_aot_init_wrapper_name (subtype);
        LLVMTypeRef func_type = NULL;
+       LLVMTypeRef arg_type = module->ptr_type;
 
        char *name = g_strdup_printf ("%s_%s", module->global_prefix, wrapper_name);
 
        switch (subtype) {
        case AOT_INIT_METHOD:
-               func_type = LLVMFunctionType1 (LLVMVoidType (), LLVMInt32Type (), FALSE);
+               func_type = LLVMFunctionType1 (LLVMVoidType (), arg_type, FALSE);
                break;
        case AOT_INIT_METHOD_GSHARED_MRGCTX:
-               func_type = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE);
-               break;
        case AOT_INIT_METHOD_GSHARED_VTABLE:
-               func_type = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE);
+               func_type = LLVMFunctionType2 (LLVMVoidType (), arg_type, IntPtrType (), FALSE);
                break;
        case AOT_INIT_METHOD_GSHARED_THIS:
-               func_type = LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), ObjRefType (), FALSE);
+               func_type = LLVMFunctionType2 (LLVMVoidType (), arg_type, ObjRefType (), FALSE);
                break;
        default:
                g_assert_not_reached ();
@@ -3038,6 +3038,8 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
 
        func = LLVMAddFunction (lmodule, name, func_type);
 
+       info_var = LLVMGetParam (func, 0);
+
        LLVMSetLinkage (func, LLVMInternalLinkage);
 
        mono_llvm_add_func_attr (func, LLVM_ATTR_NO_INLINE);
@@ -3049,9 +3051,15 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
        builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, entry_bb);
 
+       /* Load method_index which is emitted at the start of the method info */
+       indexes [0] = const_int32 (0);
+       indexes [1] = const_int32 (0);
+       // FIXME: Make sure its aligned
+       index_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, LLVMBuildBitCast (builder, info_var, LLVMPointerType (LLVMInt32Type (), 0), ""), indexes, 1, ""), "method_index");
+
        /* Check for is_inited here as well, since this can be called from JITted code which might not check it */
-       indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-       indexes [1] = LLVMGetParam (func, 0);
+       indexes [0] = const_int32 (0);
+       indexes [1] = index_var;
        inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""), "is_inited");
 
        cmp = LLVMBuildICmp (builder, LLVMIntEQ, inited_var, LLVMConstInt (LLVMTypeOf (inited_var), 0, FALSE), "");
@@ -3067,7 +3075,7 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
 
        args [0] = LLVMBuildPtrToInt (builder, module->info_var, IntPtrType (), "");
        args [1] = LLVMBuildPtrToInt (builder, amodule_var, IntPtrType (), "");
-       args [2] = LLVMGetParam (func, 0);
+       args [2] = info_var;
 
        switch (subtype) {
        case AOT_INIT_METHOD:
@@ -3093,13 +3101,17 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
                break;
        }
 
-       icall_sig = LLVMFunctionType4 (LLVMVoidType (), IntPtrType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
+       /* Call the mini_llvm_init_method JIT icall */
+       icall_sig = LLVMFunctionType4 (LLVMVoidType (), IntPtrType (), IntPtrType (), arg_type, IntPtrType (), FALSE);
        callee = get_aotconst_module (module, builder, MONO_PATCH_INFO_JIT_ICALL_ID, GINT_TO_POINTER (MONO_JIT_ICALL_mini_llvm_init_method), LLVMPointerType (icall_sig, 0), NULL, NULL);
        LLVMBuildCall (builder, callee, args, LLVMCountParamTypes (icall_sig), "");
 
-       // Set the inited flag
-       indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-       indexes [1] = LLVMGetParam (func, 0);
+       /*
+        * Set the inited flag
+        * This is already done by the LLVM methods themselves, but its needed by JITted methods.
+        */
+       indexes [0] = const_int32 (0);
+       indexes [1] = index_var;
        LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, module->inited_var, indexes, 2, ""));
 
        LLVMBuildBr (builder, inited_bb);
@@ -3107,7 +3119,7 @@ emit_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
        LLVMPositionBuilderAtEnd (builder, inited_bb);
        LLVMBuildRetVoid (builder);
 
-       LLVMVerifyFunction(func, LLVMAbortProcessAction);
+       LLVMVerifyFunction (func, LLVMAbortProcessAction);
        LLVMDisposeBuilder (builder);
        g_free (name);
 
@@ -3162,16 +3174,16 @@ emit_icall_cold_wrapper (MonoLLVMModule *module, LLVMModuleRef lmodule, MonoJitI
  * cold calling convention.
  */
 static void
-emit_init_icall_wrappers (MonoLLVMModule *module)
+emit_init_funcs (MonoLLVMModule *module)
 {
-       module->init_method = emit_init_icall_wrapper (module, AOT_INIT_METHOD);
-       module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_MRGCTX);
-       module->init_method_gshared_this = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_THIS);
-       module->init_method_gshared_vtable = emit_init_icall_wrapper (module, AOT_INIT_METHOD_GSHARED_VTABLE);
+       module->init_method = emit_init_func (module, AOT_INIT_METHOD);
+       module->init_method_gshared_mrgctx = emit_init_func (module, AOT_INIT_METHOD_GSHARED_MRGCTX);
+       module->init_method_gshared_this = emit_init_func (module, AOT_INIT_METHOD_GSHARED_THIS);
+       module->init_method_gshared_vtable = emit_init_func (module, AOT_INIT_METHOD_GSHARED_VTABLE);
 }
 
 static LLVMValueRef
-get_init_icall_wrapper (MonoLLVMModule *module, MonoAotInitSubtype subtype)
+get_init_func (MonoLLVMModule *module, MonoAotInitSubtype subtype)
 {
        switch (subtype) {
        case AOT_INIT_METHOD:
@@ -3335,12 +3347,12 @@ emit_div_check (EmitContext *ctx, LLVMBuilderRef builder, MonoBasicBlock *bb, Mo
 }
 
 /*
- * emit_init_method:
+ * emit_method_init:
  *
  *   Emit code to initialize the GOT slots used by the method.
  */
 static void
-emit_init_method (EmitContext *ctx)
+emit_method_init (EmitContext *ctx)
 {
        LLVMValueRef indexes [16], args [16], callee;
        LLVMValueRef inited_var, cmp, call;
@@ -3350,8 +3362,8 @@ emit_init_method (EmitContext *ctx)
 
        ctx->module->max_inited_idx = MAX (ctx->module->max_inited_idx, cfg->method_index);
 
-       indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-       indexes [1] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, FALSE);
+       indexes [0] = const_int32 (0);
+       indexes [1] = const_int32 (cfg->method_index);
        inited_var = LLVMBuildLoad (builder, LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""), "is_inited");
 
        args [0] = inited_var;
@@ -3368,26 +3380,30 @@ emit_init_method (EmitContext *ctx)
        builder = ctx->builder = create_builder (ctx);
        LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
 
+       LLVMTypeRef type = LLVMArrayType (LLVMInt8Type (), 0);
+       char *symbol = g_strdup_printf ("info_dummy_%s", cfg->llvm_method_name);
+       LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, type, symbol);
+       g_free (symbol);
+       cfg->llvm_dummy_info_var = info_var;
+
+       args [0] = convert (ctx, info_var, ctx->module->ptr_type);
+
        // FIXME: Cache
        if (ctx->rgctx_arg && ((cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) ||
                                                   mini_method_is_default_method (cfg->method))) {
-               args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
                args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
                callee = ctx->module->init_method_gshared_mrgctx;
                call = LLVMBuildCall (builder, callee, args, 2, "");
        } else if (ctx->rgctx_arg) {
                /* A vtable is passed as the rgctx argument */
-               args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
                args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
                callee = ctx->module->init_method_gshared_vtable;
                call = LLVMBuildCall (builder, callee, args, 2, "");
        } else if (cfg->gshared) {
-               args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
                args [1] = convert (ctx, ctx->this_arg, ObjRefType ());
                callee = ctx->module->init_method_gshared_this;
                call = LLVMBuildCall (builder, callee, args, 2, "");
        } else {
-               args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
                callee = ctx->module->init_method;
                call = LLVMBuildCall (builder, callee, args, 1, "");
        }
@@ -3398,6 +3414,11 @@ emit_init_method (EmitContext *ctx)
         */
        set_call_cold_cconv (call);
 
+       // Set the inited flag
+       indexes [0] = const_int32 (0);
+       indexes [1] = const_int32 (cfg->method_index);
+       LLVMBuildStore (builder, LLVMConstInt (LLVMInt8Type (), 1, FALSE), LLVMBuildGEP (builder, ctx->module->inited_var, indexes, 2, ""));
+
        LLVMBuildBr (builder, inited_bb);
        ctx->bblocks [cfg->bb_entry->block_num].end_bblock = inited_bb;
 
@@ -9214,7 +9235,7 @@ emit_method_inner (EmitContext *ctx)
        if (cfg->method->wrapper_type == MONO_WRAPPER_OTHER) {
                WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
                if (info->subtype == WRAPPER_SUBTYPE_AOT_INIT) {
-                       method = get_init_icall_wrapper (ctx->module, info->d.aot_init.subtype);
+                       method = get_init_func (ctx->module, info->d.aot_init.subtype);
                        ctx->lmethod = method;
                        ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
 
@@ -9754,7 +9775,7 @@ after_codegen_1:
                if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)
                        needs_init = FALSE;
                if (needs_init)
-                       emit_init_method (ctx);
+                       emit_method_init (ctx);
                else
                        LLVMBuildBr (ctx->builder, ctx->inited_bb);
 
@@ -9769,9 +9790,8 @@ after_codegen_1:
                mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
 
 after_codegen:
+       g_ptr_array_add (ctx->module->cfgs, cfg);
        if (cfg->llvm_only) {
-               g_ptr_array_add (ctx->module->cfgs, cfg);
-
                /*
                 * Add the contents of ctx->callsite_list to module->callsite_list.
                 * We can't do this earlier, as it contains llvm instructions which can be
@@ -9820,7 +9840,7 @@ after_codegen:
                }
 
                //LLVMDumpValue (ctx->lmethod);
-               //int err = LLVMVerifyFunction(ctx->lmethod, LLVMPrintMessageAction);
+               //int err = LLVMVerifyFunction (ctx->lmethod, LLVMPrintMessageAction);
                //g_assert (err == 0);
        } else {
                //LLVMVerifyFunction (method, 0);
@@ -10282,6 +10302,16 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
        module->cfgs = g_ptr_array_new ();
        module->intrins_by_id = g_new0 (LLVMValueRef, INTRINS_NUM);
        module->aotconst_vars = g_hash_table_new (NULL, NULL);
+       module->llvm_types = g_hash_table_new (NULL, NULL);
+       module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
+       module->plt_entries_ji = g_hash_table_new (NULL, NULL);
+       module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
+       module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
+       module->method_to_lmethod = g_hash_table_new (NULL, NULL);
+       module->method_to_call_info = g_hash_table_new (NULL, NULL);
+       module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
+       module->no_method_table_lmethods = g_hash_table_new (NULL, NULL);
+       module->callsite_list = g_ptr_array_new ();
 
        if (llvm_only)
                /* clang ignores our debug info because it has an invalid version */
@@ -10370,7 +10400,7 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
        emit_llvm_code_start (module);
 
        // Needs idx_to_lmethod
-       emit_init_icall_wrappers (module);
+       emit_init_funcs (module);
 
        /* Add a dummy personality function */
        if (!use_mono_personality_debug) {
@@ -10390,17 +10420,6 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
                LLVMSetLinkage (module->sentinel_exception, LLVMExternalLinkage);
                mono_llvm_set_is_constant (module->sentinel_exception);
        }
-
-       module->llvm_types = g_hash_table_new (NULL, NULL);
-       module->plt_entries = g_hash_table_new (g_str_hash, g_str_equal);
-       module->plt_entries_ji = g_hash_table_new (NULL, NULL);
-       module->direct_callables = g_hash_table_new (g_str_hash, g_str_equal);
-       module->idx_to_lmethod = g_hash_table_new (NULL, NULL);
-       module->method_to_lmethod = g_hash_table_new (NULL, NULL);
-       module->method_to_call_info = g_hash_table_new (NULL, NULL);
-       module->idx_to_unbox_tramp = g_hash_table_new (NULL, NULL);
-       module->no_method_table_lmethods = g_hash_table_new (NULL, NULL);
-       module->callsite_list = g_ptr_array_new ();
 }
 
 void
@@ -10552,9 +10571,10 @@ mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
  * mono_llvm_emit_aot_data:
  *
  *   Emit the binary data DATA pointed to by symbol SYMBOL.
+ * Return the LLVM variable for the data.
  */
-void
-mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+gpointer
+mono_llvm_emit_aot_data_aligned (const char *symbol, guint8 *data, int data_len, int align)
 {
        MonoLLVMModule *module = &aot_module;
        LLVMTypeRef type;
@@ -10565,8 +10585,16 @@ mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
        LLVMSetVisibility (d, LLVMHiddenVisibility);
        LLVMSetLinkage (d, LLVMInternalLinkage);
        LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
-       LLVMSetAlignment (d, 8);
+       if (align != 1)
+               LLVMSetAlignment (d, align);
        mono_llvm_set_is_constant (d);
+       return d;
+}
+
+gpointer
+mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+{
+       return mono_llvm_emit_aot_data_aligned (symbol, data, data_len, 8);
 }
 
 /* Add a reference to a global defined in JITted code */
@@ -10709,6 +10737,7 @@ emit_aot_file_info (MonoLLVMModule *module)
                fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "llvm_got_info_offsets");
                fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "image_table");
                fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "weak_field_indexes");
+               fields [tindex ++] = LLVMGetNamedGlobal (lmodule, "method_flags_table");
        }
        /* Not needed (mem_end) */
        fields [tindex ++] = LLVMConstNull (eltype);
@@ -10989,6 +11018,24 @@ mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
        mono_llvm_replace_uses_of (module->inited_var, real_inited);
        LLVMDeleteGlobal (module->inited_var);
 
+       /* Replace the dummy info_ variables with the real ones */
+       for (int i = 0; i < module->cfgs->len; ++i) {
+               MonoCompile *cfg = (MonoCompile *)g_ptr_array_index (module->cfgs, i);
+
+               // FIXME: Eliminate unused vars
+
+               // FIXME: Speed this up
+               if (cfg->llvm_dummy_info_var) {
+                       if (cfg->llvm_info_var) {
+                               mono_llvm_replace_uses_of (cfg->llvm_dummy_info_var, cfg->llvm_info_var);
+                       LLVMDeleteGlobal (cfg->llvm_dummy_info_var);
+                       } else {
+                               // FIXME: How can this happen ?
+                               LLVMSetInitializer (cfg->llvm_dummy_info_var, mono_llvm_create_constant_data_array (NULL, 0));
+                       }
+               }
+       }
+
        if (module->llvm_only) {
                emit_get_method (&aot_module);
                emit_get_unbox_tramp (&aot_module);
index 6662764..ad23192 100644 (file)
@@ -25,7 +25,8 @@ void mono_llvm_emit_call                (MonoCompile *cfg, MonoCallInst *call);
 void mono_llvm_create_aot_module        (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, LLVMModuleFlags flags);
 void mono_llvm_emit_aot_module          (const char *filename, const char *cu_name);
 void mono_llvm_emit_aot_file_info       (MonoAotFileInfo *info, gboolean has_jitted_code);
-void mono_llvm_emit_aot_data            (const char *symbol, guint8 *data, int data_len);
+gpointer mono_llvm_emit_aot_data        (const char *symbol, guint8 *data, int data_len);
+gpointer mono_llvm_emit_aot_data_aligned (const char *symbol, guint8 *data, int data_len, int align);
 void mono_llvm_check_method_supported   (MonoCompile *cfg);
 void mono_llvm_free_domain_info         (MonoDomain *domain);
 MONO_API void mono_personality              (void);
index 1fe5b7c..1d217a6 100644 (file)
@@ -4844,7 +4844,7 @@ register_icalls (void)
 
        register_dyn_icall (mini_get_dbg_callbacks ()->user_break, mono_debugger_agent_user_break, mono_icall_sig_void, FALSE);
 
-       register_icall (mini_llvm_init_method, mono_icall_sig_void_ptr_ptr_int_ptr, TRUE);
+       register_icall (mini_llvm_init_method, mono_icall_sig_void_ptr_ptr_ptr_ptr, TRUE);
        register_icall_no_wrapper (mini_llvmonly_resolve_iface_call_gsharedvt, mono_icall_sig_ptr_object_int_ptr_ptr);
        register_icall_no_wrapper (mini_llvmonly_resolve_vcall_gsharedvt, mono_icall_sig_ptr_object_int_ptr_ptr);
        register_icall_no_wrapper (mini_llvmonly_resolve_generic_virtual_call, mono_icall_sig_ptr_ptr_int_ptr);
index c734426..8fb697c 100644 (file)
@@ -4244,7 +4244,14 @@ mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
        g_assert_not_reached ();
 }
 
-void mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+gpointer
+mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+{
+       g_assert_not_reached ();
+}
+
+gpointer
+mono_llvm_emit_aot_data_aligned (const char *symbol, guint8 *data, int data_len, int align)
 {
        g_assert_not_reached ();
 }
index 8ebb1a2..b9321bc 100644 (file)
@@ -1539,9 +1539,11 @@ typedef struct {
 
        /* Used by AOT */
        guint32 got_offset, ex_info_offset, method_info_offset, method_index;
+       guint32 aot_method_flags;
        /* For llvm */
        guint32 got_access_count;
        gpointer llvmonly_init_cond;
+       gpointer llvm_dummy_info_var, llvm_info_var;
        /* Symbol used to refer to this method in generated assembly */
        char *asm_symbol;
        char *asm_debug_symbol;