#endif
/* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 4
+#define N_COMMON_GOT_ENTRIES 9
#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
guint32 image_table_len;
gboolean out_of_date;
gboolean plt_inited;
+ gboolean got_initializing;
guint8 *mem_begin;
guint8 *mem_end;
guint8 *jit_code_start;
compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end);
static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass);
-
-/*****************************************************/
-/* AOT RUNTIME */
-/*****************************************************/
+init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context);
static inline void
amodule_lock (MonoAotModule *amodule)
msg = g_strdup_printf ("compiled with --aot=full");
usable = FALSE;
}
+ if (mono_llvm_only && !(info->flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) {
+ msg = g_strdup_printf ("not compiled with --aot=llvmonly");
+ usable = FALSE;
+ }
#ifdef TARGET_ARM
/* mono_arch_find_imt_method () requires this */
if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
}
}
+static void
+init_amodule_got (MonoAotModule *amodule)
+{
+ MonoJumpInfo ji;
+
+ /* These can't be initialized in load_aot_module () */
+ if (!amodule->shared_got [6] && !amodule->got_initializing) {
+ amodule->got_initializing = TRUE;
+
+ memset (&ji, 0, sizeof (ji));
+ ji.type = MONO_PATCH_INFO_INTERNAL_METHOD;
+ ji.data.name = "mono_aot_init_llvm_method";
+ amodule->got_initializing = TRUE;
+ amodule->shared_got [6] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+ ji.data.name = "mono_aot_init_gshared_method_this";
+ 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);
+ init_gots (amodule);
+ }
+}
+
static void
load_aot_module (MonoAssembly *assembly, gpointer user_data)
{
for (i = 0; i < amodule->info.nmethods; ++i) {
void *addr = NULL;
+ if (amodule->info.llvm_get_method) {
+ gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+ addr = get_method (i);
+ }
+
/* method_addresses () contains a table of branches, since the ios linker can update those correctly */
if (!addr && amodule->info.method_addresses) {
addr = get_call_table_entry (amodule->info.method_addresses, i);
amodule->shared_got [3] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
}
+ amodule->shared_got [5] = amodule;
+ /* Can't initialize the other shared got slots yet, they are initialized in init_amodule_got () */
+
init_gots (amodule);
/*
int version, fde_count;
gint32 *table;
+ if (amodule->info.llvm_get_method) {
+ gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+ *code_start = get_method (-1);
+ *code_end = get_method (-2);
+
+ g_assert (*code_end > *code_start);
+ return;
+ }
+
g_assert (amodule->mono_eh_frame);
p = amodule->mono_eh_frame;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
ji->data.index = decode_value (p, &p);
break;
- case MONO_PATCH_INFO_RGCTX_FETCH: {
+ case MONO_PATCH_INFO_RGCTX_FETCH:
+ case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
gboolean res;
MonoJumpInfoRgctxEntry *entry;
guint32 offset, val;
break;
}
case MONO_PATCH_INFO_SEQ_POINT_INFO:
+ case MONO_PATCH_INFO_AOT_MODULE:
break;
case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE: {
MonoJumpInfoImtTramp *imt_tramp = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoImtTramp));
static gpointer
load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
{
- MonoClass *klass;
- gboolean from_plt = method == NULL;
MonoJitInfo *jinfo = NULL;
guint8 *code = NULL, *info;
gboolean res;
+ init_amodule_got (amodule);
+
if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
if (mono_aot_only)
/* The caller cannot handle this */
if (amodule->out_of_date)
return NULL;
+ if (amodule->info.llvm_get_method) {
+ /*
+ * Obtain the method address by calling a generated function in the LLVM module.
+ */
+ gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+ code = get_method (method_index);
+ }
+
if (!code) {
if (amodule->methods [method_index] == GINT_TO_POINTER (-1)) {
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
}
return NULL;
}
+ code = amodule->methods [method_index];
}
- code = amodule->methods [method_index];
-
info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
if (!amodule->methods_loaded) {
}
}
- res = init_method (amodule, method_index, method, &klass);
- if (!res)
- goto cleanup;
+ if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY))) {
+ res = init_method (amodule, method_index, method, NULL, NULL);
+ if (!res)
+ goto cleanup;
+ }
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
char *full_name;
mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
}
- if (from_plt && klass && !klass->generic_container)
- mono_runtime_class_init (mono_class_vtable (domain, klass));
-
return code;
cleanup:
}
static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass)
+init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
{
MonoDomain *domain = mono_domain_get ();
MonoMemPool *mp;
+ MonoClass *klass;
+ gboolean from_plt = method == NULL;
int pindex, n_patches;
guint8 *p;
MonoJitInfo *jinfo = NULL;
p = info;
if (method) {
- *klass = method->klass;
+ klass = method->klass;
decode_klass_ref (amodule, p, &p);
} else {
- *klass = decode_klass_ref (amodule, p, &p);
+ klass = decode_klass_ref (amodule, p, &p);
}
n_patches = decode_value (p, &p);
* finished executing (#23242).
*/
if (!got [got_slots [pindex]] || ji->type == MONO_PATCH_INFO_SFLDA) {
+ /* In llvm-only made, we might encounter shared methods */
+ if (mono_llvm_only && ji->type == MONO_PATCH_INFO_METHOD && mono_method_check_context_used (ji->data.method)) {
+ MonoError error;
+
+ g_assert (context);
+ ji->data.method = mono_class_inflate_generic_method_checked (ji->data.method, context, &error);
+ }
addr = mono_resolve_patch_target (method, domain, code, ji, TRUE);
if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
addr = mono_create_ftnptr (domain, addr);
if (mini_get_debug_options ()->load_aot_jit_info_eagerly)
jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
+ if (init_class)
+ mono_runtime_class_init (mono_class_vtable (domain, init_class));
+ else if (from_plt && klass && !klass->generic_container)
+ mono_runtime_class_init (mono_class_vtable (domain, klass));
+
return TRUE;
cleanup:
return FALSE;
}
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+ gboolean res;
+
+ // FIXME: Handle failure
+ res = init_method ((MonoAotModule*)aot_module, method_index, NULL, NULL, NULL);
+ g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+ gboolean res;
+ MonoClass *klass;
+
+ // FIXME:
+ g_assert (this);
+
+ // FIXME: Handle failure
+ klass = this->vtable->klass;
+ res = init_method ((MonoAotModule*)aot_module, method_index, NULL, klass, klass->generic_class ? &klass->generic_class->context : NULL);
+ g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+ gboolean res;
+ MonoGenericContext context = { NULL, NULL };
+ MonoClass *klass = rgctx->class_vtable->klass;
+
+ if (klass->generic_class)
+ context.class_inst = klass->generic_class->context.class_inst;
+ else if (klass->generic_container)
+ context.class_inst = klass->generic_container->context.class_inst;
+ context.method_inst = rgctx->method_inst;
+
+ res = init_method ((MonoAotModule*)aot_module, method_index, NULL, rgctx->class_vtable->klass, &context);
+ g_assert (res);
+}
+
/*
* mono_aot_get_method:
*
/* Same for CompareExchange<T> and Exchange<T> */
/* Same for Volatile.Read<T>/Write<T> */
if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass->image == mono_defaults.corlib &&
- ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1])) ||
- (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->ret))) ||
- (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1]))))) {
+ ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->params [1]))) ||
+ (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret)))) ||
+ (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->params [1])))))) {
MonoError error;
MonoMethod *m;
MonoGenericContext ctx;
if (amodule->plt_inited)
return;
+ if (amodule->info.plt_size <= 1) {
+ amodule->plt_inited = TRUE;
+ return;
+ }
+
tramp = mono_create_specific_trampoline (amodule, MONO_TRAMPOLINE_AOT_PLT, mono_get_root_domain (), NULL);
/*
return amodule;
}
+static void
+no_trampolines (void)
+{
+ g_assert_not_reached ();
+}
+
/*
* Return the trampoline identified by NAME from the mscorlib AOT file.
* On ppc64, this returns a function descriptor.
{
MonoAotModule *amodule = get_mscorlib_aot_module ();
+ /*
+ if (mono_llvm_only)
+ return no_trampolines;
+ */
+
return mono_create_ftnptr_malloc (load_function_full (amodule, name, out_tinfo));
}
g_assert (amodule);
}
+ if (amodule->info.llvm_get_unbox_tramp) {
+ gpointer (*get_tramp) (int) = amodule->info.llvm_get_unbox_tramp;
+ code = get_tramp (method_index);
+
+ if (code)
+ return code;
+ }
+
ut = amodule->unbox_trampolines;
ut_end = amodule->unbox_trampolines_end;