#include <mono/metadata/assembly.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/marshal.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/mono-endian.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-mmap.h>
-#include "mono/utils/mono-compiler.h"
+#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-digest.h>
#include "seq-points.h"
#include "version.h"
#include "debugger-agent.h"
+#include "aot-compiler.h"
#ifndef DISABLE_AOT
#endif
/* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 4
+#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)))
/* Pointer to the Global Offset Table */
gpointer *got;
gpointer *llvm_got;
- gpointer shared_got [N_COMMON_GOT_ENTRIES];
+ gpointer *shared_got;
GHashTable *name_cache;
GHashTable *extra_methods;
/* Maps methods to their code */
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);
+init_llvm_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context);
-/*****************************************************/
-/* AOT RUNTIME */
-/*****************************************************/
+static MonoJumpInfo*
+decode_patches (MonoAotModule *amodule, MonoMemPool *mp, int n_patches, gboolean llvm, guint32 *got_offsets);
static inline void
amodule_lock (MonoAotModule *amodule)
MonoType *gshared_constraint = NULL;
char *par_name = NULL;
+ t = NULL;
if (has_container) {
gboolean is_method = decode_value (p, &p);
} else {
gboolean has_gshared_constraint = decode_value (p, &p);
if (has_gshared_constraint) {
- int len;
+ MonoClass *par_klass;
gshared_constraint = decode_type (module, p, &p);
if (!gshared_constraint)
return NULL;
- len = decode_value (p, &p);
- if (len) {
- par_name = mono_image_alloc (module->assembly->image, len + 1);
- memcpy (par_name, p, len);
- p += len;
- par_name [len] = '\0';
- }
+ par_klass = decode_klass_ref (module, p, &p);
+ if (!par_klass)
+ return NULL;
+
+ t = mini_get_shared_gparam (&par_klass->byval_arg, gshared_constraint);
}
}
- t = g_new0 (MonoType, 1);
- t->type = type;
- if (container) {
- t->data.generic_param = mono_generic_container_get_param (container, num);
- g_assert (gshared_constraint == NULL);
+ if (t) {
+ klass = mono_class_from_mono_type (t);
} else {
- /* Anonymous */
- MonoGenericParam *par = (MonoGenericParam*)mono_image_alloc0 (module->assembly->image, sizeof (MonoGenericParamFull));
- par->num = num;
- par->gshared_constraint = gshared_constraint;
- // FIXME:
- par->image = mono_defaults.corlib;
- t->data.generic_param = par;
- if (par_name)
- ((MonoGenericParamFull*)par)->info.name = par_name;
- }
-
- // FIXME: Maybe use types directly to avoid
- // the overhead of creating MonoClass-es
- klass = mono_class_from_mono_type (t);
+ t = g_new0 (MonoType, 1);
+ t->type = type;
+ if (container) {
+ t->data.generic_param = mono_generic_container_get_param (container, num);
+ g_assert (gshared_constraint == NULL);
+ } else {
+ /* Anonymous */
+ MonoGenericParam *par = (MonoGenericParam*)mono_image_alloc0 (module->assembly->image, sizeof (MonoGenericParamFull));
+ par->num = num;
+ par->gshared_constraint = gshared_constraint;
+ par->image = module->assembly->image;
+ t->data.generic_param = par;
+ if (par_name)
+ ((MonoGenericParamFull*)par)->info.name = par_name;
+ }
+ // FIXME: Maybe use types directly to avoid
+ // the overhead of creating MonoClass-es
+ klass = mono_class_from_mono_type (t);
- g_free (t);
+ g_free (t);
+ }
break;
}
case MONO_AOT_TYPEREF_ARRAY:
}
if (image_index == MONO_AOT_METHODREF_WRAPPER) {
+ WrapperInfo *info;
guint32 wrapper_type;
wrapper_type = decode_value (p, &p);
g_error ("Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
break;
}
- case MONO_WRAPPER_WRITE_BARRIER:
+ case MONO_WRAPPER_WRITE_BARRIER: {
ref->method = mono_gc_get_write_barrier ();
break;
+ }
case MONO_WRAPPER_STELEMREF: {
int subtype = decode_value (p, &p);
ref->method = mono_marshal_get_stelemref ();
} else if (subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF) {
int kind;
- WrapperInfo *info;
kind = decode_value (p, &p);
ref->method = mono_marshal_get_array_address (rank, elem_size);
} else if (subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
- WrapperInfo *info;
MonoMethod *m;
m = decode_resolve_method_ref (module, p, &p);
}
case MONO_WRAPPER_RUNTIME_INVOKE: {
int subtype = decode_value (p, &p);
+ int pass_rgctx = decode_value (p, &p);
if (!target)
return FALSE;
if (!m)
return FALSE;
- ref->method = mono_marshal_get_runtime_invoke (m, FALSE);
+ ref->method = mono_marshal_get_runtime_invoke (m, FALSE, pass_rgctx);
} else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) {
/* Virtual direct wrapper */
MonoMethod *m = decode_resolve_method_ref (module, p, &p);
if (!m)
return FALSE;
- ref->method = mono_marshal_get_runtime_invoke (m, TRUE);
+ ref->method = mono_marshal_get_runtime_invoke (m, TRUE, pass_rgctx);
} else {
MonoMethodSignature *sig;
- WrapperInfo *info;
sig = decode_signature_with_target (module, NULL, p, &p);
info = mono_marshal_get_wrapper_info (target);
if (info->subtype != subtype)
return FALSE;
+ if (info->d.runtime_invoke.pass_rgctx != pass_rgctx)
+ return FALSE;
g_assert (info->d.runtime_invoke.sig);
if (mono_metadata_signature_equal (sig, info->d.runtime_invoke.sig))
ref->method = target;
return FALSE;
if (wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) {
- WrapperInfo *info;
-
subtype = decode_value (p, &p);
info = mono_marshal_get_wrapper_info (target);
if (info) {
char *build_info;
char *msg = NULL;
gboolean usable = TRUE;
- gboolean full_aot;
+ gboolean full_aot, safepoints;
guint8 *blob;
guint32 excluded_cpu_optimizations;
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) {
}
}
+ safepoints = info->flags & MONO_AOT_FILE_FLAG_SAFEPOINTS;
+
+ if (!safepoints && mono_threads_is_coop_enabled ()) {
+ msg = g_strdup_printf ("not compiled with safepoints");
+ usable = FALSE;
+ }
+
*out_msg = msg;
return usable;
}
#endif
}
+/*
+ * init_amodule_got:
+ *
+ * Initialize the shared got entries for AMODULE.
+ */
static void
-init_gots (MonoAotModule *amodule)
+init_amodule_got (MonoAotModule *amodule)
{
- int i;
+ MonoJumpInfo *ji;
+ MonoMemPool *mp;
+ MonoJumpInfo *patches;
+ guint32 got_offsets [128];
+ int i, npatches;
+
+ /* These can't be initialized in load_aot_module () */
+ if (amodule->shared_got [0] || amodule->got_initializing)
+ return;
+
+ amodule->got_initializing = TRUE;
+
+ mp = mono_mempool_new ();
+ npatches = amodule->info.nshared_got_entries;
+ for (i = 0; i < npatches; ++i)
+ got_offsets [i] = i;
+ patches = decode_patches (amodule, mp, npatches, FALSE, got_offsets);
+ g_assert (patches);
+ for (i = 0; i < npatches; ++i) {
+ ji = &patches [i];
+
+ if (ji->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR && !mono_gc_is_moving ()) {
+ amodule->shared_got [i] = NULL;
+ } else if (ji->type == MONO_PATCH_INFO_GC_NURSERY_START && !mono_gc_is_moving ()) {
+ amodule->shared_got [i] = NULL;
+ } else if (ji->type == MONO_PATCH_INFO_GC_NURSERY_BITS && !mono_gc_is_moving ()) {
+ amodule->shared_got [i] = NULL;
+ } else if (ji->type == MONO_PATCH_INFO_IMAGE) {
+ amodule->shared_got [i] = amodule->assembly->image;
+ } else if (ji->type == MONO_PATCH_INFO_MSCORLIB_GOT_ADDR) {
+ if (mono_defaults.corlib) {
+ MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
+
+ if (mscorlib_amodule)
+ amodule->shared_got [i] = mscorlib_amodule->got;
+ } else {
+ amodule->shared_got [i] = amodule->got;
+ }
+ } else if (ji->type == MONO_PATCH_INFO_AOT_MODULE) {
+ amodule->shared_got [i] = amodule;
+ } else {
+ amodule->shared_got [i] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, ji, FALSE);
+ }
+ }
if (amodule->got) {
- for (i = 0; i < N_COMMON_GOT_ENTRIES; ++i)
+ for (i = 0; i < npatches; ++i)
amodule->got [i] = amodule->shared_got [i];
}
if (amodule->llvm_got) {
- for (i = 0; i < N_COMMON_GOT_ENTRIES; ++i)
+ for (i = 0; i < npatches; ++i)
amodule->llvm_got [i] = amodule->shared_got [i];
}
+
+ mono_mempool_destroy (mp);
}
static void
amodule->globals = globals;
amodule->sofile = sofile;
amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ amodule->extra_methods = g_hash_table_new (NULL, NULL);
amodule->blob = blob;
+ amodule->shared_got = g_new0 (gpointer, info->nshared_got_entries);
mono_mutex_init_recursive (&amodule->mutex);
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);
assembly->image->aot_module = amodule;
- amodule->shared_got [0] = assembly->image;
-
if (mono_aot_only) {
char *code;
find_symbol (amodule->sofile, amodule->globals, "specific_trampolines_page", (gpointer *)&code);
amodule->use_page_trampolines = code != NULL;
/*g_warning ("using page trampolines: %d", amodule->use_page_trampolines);*/
- if (mono_defaults.corlib) {
- /* The second got slot contains the mscorlib got addr */
- MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
-
- amodule->shared_got [1] = mscorlib_amodule->got;
- } else {
- amodule->shared_got [1] = amodule->got;
- }
- }
-
- if (mono_gc_is_moving ()) {
- MonoJumpInfo ji;
-
- memset (&ji, 0, sizeof (ji));
- ji.type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
- amodule->shared_got [2] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
-
- memset (&ji, 0, sizeof (ji));
- ji.type = MONO_PATCH_INFO_GC_NURSERY_START;
- amodule->shared_got [3] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
}
- init_gots (amodule);
-
/*
* Register the plt region as a single trampoline so we can unwind from this code
*/
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: loaded AOT Module for %s.\n", assembly->image->name);
}
-/*
- * mono_aot_register_globals:
- *
- * This is called by the ctor function in AOT images compiled with the
- * 'no-dlsym' option.
- */
-void
-mono_aot_register_globals (gpointer *globals)
-{
- g_assert_not_reached ();
-}
-
/*
* mono_aot_register_module:
*
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;
*/
static MonoJitInfo*
decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
- MonoMethod *method, guint8 *code,
+ MonoMethod *method, guint8 *code, guint32 code_len,
MonoJitExceptionInfo *clauses, int num_clauses,
MonoJitInfoFlags flags,
GSList **nesting,
guint8 *fde, *cie, *code_start, *code_end;
int version, fde_count;
gint32 *table;
- int i, pos, left, right, code_len;
+ int i, pos, left, right;
MonoJitExceptionInfo *ei;
guint32 fde_len, ei_len, nested_len, nindex;
gpointer *type_info;
MonoJitInfo *jinfo;
MonoLLVMFDEInfo info;
- g_assert (amodule->mono_eh_frame);
+ if (!amodule->mono_eh_frame) {
+ jinfo = mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, num_clauses, 0));
+ mono_jit_info_init (jinfo, method, code, code_len, flags, num_clauses, 0);
+ memcpy (jinfo->clauses, clauses, num_clauses * sizeof (MonoJitExceptionInfo));
+ return jinfo;
+ }
+
+ g_assert (amodule->mono_eh_frame && code);
p = amodule->mono_eh_frame;
} else {
code_end = amodule->methods [table [(pos + 1) * 2]];
}
- code_len = code_end - code_start;
+ if (!code_len)
+ code_len = code_end - code_start;
g_assert (code >= code_start && code < code_end);
*/
static MonoJitInfo*
decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
- MonoMethod *method, guint8* ex_info, guint8 *addr,
+ MonoMethod *method, guint8* ex_info,
guint8 *code, guint32 code_len)
{
int i, buf_len, num_clauses, len;
if (decode_value (p, &p))
ei->data.catch_class = decode_klass_ref (amodule, p, &p);
+ ei->clause_index = i;
+
+ ei->try_offset = decode_value (p, &p);
+ ei->try_len = decode_value (p, &p);
+ ei->handler_offset = decode_value (p, &p);
+ ei->handler_len = decode_value (p, &p);
+
/* Read the list of nesting clauses */
while (TRUE) {
int nesting_index = decode_value (p, &p);
}
}
- jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, flags, nesting, &this_reg, &this_offset);
+ jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, code_len, clauses, num_clauses, flags, nesting, &this_reg, &this_offset);
g_free (clauses);
for (i = 0; i < num_clauses; ++i)
//printf ("F: %s\n", mono_method_full_name (method, TRUE));
- jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, addr, code, code_len);
+ jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, code, code_len);
g_assert ((guint8*)addr >= (guint8*)jinfo->code_start);
if (!ji->data.del_tramp->method)
goto cleanup;
}
- ji->data.del_tramp->virtual = decode_value (p, &p) ? TRUE : FALSE;
+ ji->data.del_tramp->is_virtual = decode_value (p, &p) ? TRUE : FALSE;
break;
case MONO_PATCH_INFO_IMAGE:
ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
+ case MONO_PATCH_INFO_GC_NURSERY_BITS:
case MONO_PATCH_INFO_JIT_TLS_ID:
break;
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:
+ case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
break;
case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE: {
MonoJumpInfoImtTramp *imt_tramp = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoImtTramp));
}
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
break;
+ case MONO_PATCH_INFO_AOT_JIT_INFO:
+ ji->data.index = decode_value (p, &p);
+ break;
default:
g_warning ("unhandled type %d", ji->type);
g_assert_not_reached ();
return FALSE;
}
+/*
+ * decode_patches:
+ *
+ * Decode a list of patches identified by the got offsets in GOT_OFFSETS. Return an array of
+ * MonoJumpInfo structures allocated from MP.
+ */
static MonoJumpInfo*
-load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches,
- gboolean llvm, guint32 **got_slots,
- guint8 *buf, guint8 **endbuf)
+decode_patches (MonoAotModule *amodule, MonoMemPool *mp, int n_patches, gboolean llvm, guint32 *got_offsets)
{
MonoJumpInfo *patches;
- int pindex;
- guint8 *p;
+ MonoJumpInfo *ji;
gpointer *got;
- guint32 *got_offsets;
-
- p = buf;
+ guint32 *got_info_offsets;
+ int i;
+ gboolean res;
if (llvm) {
- got = aot_module->llvm_got;
- got_offsets = aot_module->info.llvm_got_info_offsets;
+ got = amodule->llvm_got;
+ got_info_offsets = amodule->info.llvm_got_info_offsets;
} else {
- got = aot_module->got;
- got_offsets = aot_module->info.got_info_offsets;
+ got = amodule->got;
+ got_info_offsets = amodule->info.got_info_offsets;
}
patches = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo) * n_patches);
+ for (i = 0; i < n_patches; ++i) {
+ guint8 *p = amodule->blob + mono_aot_get_offset (got_info_offsets, got_offsets [i]);
- *got_slots = g_malloc (sizeof (guint32) * n_patches);
-
- for (pindex = 0; pindex < n_patches; ++pindex) {
- MonoJumpInfo *ji = &patches [pindex];
- guint8 *shared_p;
- gboolean res;
- guint32 got_offset;
-
- got_offset = decode_value (p, &p);
-
- shared_p = aot_module->blob + mono_aot_get_offset (got_offsets, got_offset);
-
- ji->type = decode_value (shared_p, &shared_p);
+ ji = &patches [i];
+ ji->type = decode_value (p, &p);
/* See load_method () for SFLDA */
- if (got [got_offset] && ji->type != MONO_PATCH_INFO_SFLDA) {
+ if (got && got [got_offsets [i]] && ji->type != MONO_PATCH_INFO_SFLDA) {
/* Already loaded */
} else {
- res = decode_patch (aot_module, mp, ji, shared_p, &shared_p);
+ res = decode_patch (amodule, mp, ji, p, &p);
if (!res)
- goto cleanup;
+ return NULL;
}
-
- (*got_slots) [pindex] = got_offset;
}
- *endbuf = p;
return patches;
+}
- cleanup:
- g_free (*got_slots);
- *got_slots = NULL;
+static MonoJumpInfo*
+load_patch_info (MonoAotModule *amodule, MonoMemPool *mp, int n_patches,
+ gboolean llvm, guint32 **got_slots,
+ guint8 *buf, guint8 **endbuf)
+{
+ MonoJumpInfo *patches;
+ int pindex;
+ guint8 *p;
- return NULL;
+ p = buf;
+
+ *got_slots = g_malloc (sizeof (guint32) * n_patches);
+ for (pindex = 0; pindex < n_patches; ++pindex) {
+ (*got_slots)[pindex] = decode_value (p, &p);
+ }
+
+ patches = decode_patches (amodule, mp, n_patches, llvm, *got_slots);
+ if (!patches) {
+ g_free (*got_slots);
+ *got_slots = NULL;
+ return NULL;
+ }
+
+ *endbuf = p;
+ return patches;
}
static void
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) {
+ /* JITted method */
if (amodule->methods [method_index] == GINT_TO_POINTER (-1)) {
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
char *full_name;
}
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_llvm_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:
MonoMethod *w1 = mono_marshal_method_from_wrapper (method);
MonoMethod *w2 = mono_marshal_method_from_wrapper (m);
- if (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2) {
+ if ((w1 == w2) || (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2)) {
index = value;
break;
}
}
static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass)
+init_llvm_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);
}
patches = load_patch_info (amodule, mp, n_patches, llvm, &got_slots, p, &p);
- if (patches == NULL)
+ if (patches == NULL) {
+ mono_mempool_destroy (mp);
goto cleanup;
+ }
for (pindex = 0; pindex < n_patches; ++pindex) {
MonoJumpInfo *ji = &patches [pindex];
* 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);
+ }
+ /* This cannot be resolved in mono_resolve_patch_target () */
+ if (ji->type == MONO_PATCH_INFO_AOT_JIT_INFO) {
+ // FIXME: Lookup using the index
+ jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
+ ji->type = MONO_PATCH_INFO_ABS;
+ ji->data.target = jinfo;
+ }
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)
+{
+ MonoAotModule *amodule = aot_module;
+ gboolean res;
+
+ // FIXME: Handle failure
+ res = init_llvm_method (amodule, method_index, NULL, NULL, NULL);
+ g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+ MonoAotModule *amodule = aot_module;
+ gboolean res;
+ MonoClass *klass;
+ MonoGenericContext *context;
+ MonoMethod *method;
+
+ // FIXME:
+ g_assert (this);
+ klass = this->vtable->klass;
+
+ amodule_lock (amodule);
+ method = g_hash_table_lookup (amodule->extra_methods, GUINT_TO_POINTER (method_index));
+ amodule_unlock (amodule);
+
+ g_assert (method);
+ context = mono_method_get_context (method);
+ g_assert (context);
+
+ res = init_llvm_method (amodule, method_index, NULL, klass, context);
+ g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+ MonoAotModule *amodule = aot_module;
+ 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_llvm_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
+ g_assert (res);
+}
+
/*
* mono_aot_get_method:
*
/* Find method index */
method_index = 0xffffff;
if (method->is_inflated && !method->wrapper_type && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE)) {
+ MonoMethod *orig_method = method;
/*
* For generic methods, we store the fully shared instance in place of the
* original method.
*/
method = mono_method_get_declaring_generic_method (method);
method_index = mono_metadata_token_index (method->token) - 1;
+
+ if (mono_llvm_only) {
+ /* Needed by mono_aot_init_gshared_method_this () */
+ /* orig_method is a random instance but it is enough to make init_llvm_method () work */
+ amodule_lock (amodule);
+ g_hash_table_insert (amodule->extra_methods, GUINT_TO_POINTER (method_index), orig_method);
+ amodule_unlock (amodule);
+ }
} else if (method->is_inflated || !method->token) {
/* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */
amodule_lock (amodule);
/* 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 (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 (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 (mono_method_signature (method)->params [1])))))) {
MonoError error;
MonoMethod *m;
MonoGenericContext ctx;
/* Needed by find_jit_info */
amodule_lock (amodule);
- if (!amodule->extra_methods)
- amodule->extra_methods = g_hash_table_new (NULL, NULL);
g_hash_table_insert (amodule->extra_methods, GUINT_TO_POINTER (method_index), method);
amodule_unlock (amodule);
} else {
ji.type = decode_value (p, &p);
- mp = mono_mempool_new_size (512);
+ mp = mono_mempool_new ();
res = decode_patch (module, mp, &ji, p, &p);
if (!res) {
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) {
+ *out_tinfo = NULL;
+ return no_trampolines;
+ }
+
return mono_create_ftnptr_malloc (load_function_full (amodule, name, out_tinfo));
}
return amodule->trampolines [tramp_type] + (index * tramp_size);
}
+static void
+no_specific_trampoline (void)
+{
+ g_assert_not_reached ();
+}
+
/*
* Return a specific trampoline from the AOT file.
*/
static gboolean inited;
static guint32 num_trampolines;
+ if (mono_llvm_only) {
+ *code_len = 1;
+ return no_specific_trampoline;
+ }
+
if (!inited) {
mono_aot_lock ();
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;
return mono_create_ftnptr (mono_domain_get (), code);
}
+static void
+no_imt_thunk (void)
+{
+ g_assert_not_reached ();
+}
+
gpointer
mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
{
int i, index, real_count;
MonoAotModule *amodule;
+ if (mono_llvm_only)
+ return no_imt_thunk;
+
real_count = 0;
for (i = 0; i < count; ++i) {
MonoIMTCheckItem *item = imt_entries [i];
{
}
+void
+mono_aot_cleanup (void)
+{
+}
+
+guint32
+mono_aot_find_method_index (MonoMethod *method)
+{
+ g_assert_not_reached ();
+ return 0;
+}
+
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+}
+
+void
+mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+}
+
gpointer
mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
{
return NULL;
}
+gpointer
+mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
gpointer
mono_aot_get_trampoline (const char *name)
{
return NULL;
}
+gpointer
+mono_aot_get_gsharedvt_arg_trampoline (gpointer arg, gpointer addr)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+void
+mono_aot_set_make_unreadable (gboolean unreadable)
+{
+}
+
+gboolean
+mono_aot_is_pagefault (void *ptr)
+{
+ return FALSE;
+}
+
+void
+mono_aot_handle_pagefault (void *ptr)
+{
+}
+
guint8*
mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
{