#include <sys/wait.h> /* for WIFEXITED, WEXITSTATUS */
#endif
+#include <mono/metadata/abi-details.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/class.h>
#include <mono/metadata/object.h>
MonoDl *sofile;
JitInfoMap *async_jit_info_table;
+ CRITICAL_SECTION mutex;
} MonoAotModule;
typedef struct {
/* AOT RUNTIME */
/*****************************************************/
+static inline void
+amodule_lock (MonoAotModule *amodule)
+{
+ EnterCriticalSection (&amodule->mutex);
+}
+
+static inline void
+amodule_unlock (MonoAotModule *amodule)
+{
+ LeaveCriticalSection (&amodule->mutex);
+}
+
/*
* load_image:
*
offset = (((int)ins & 0xffffff) << 8) >> 8;
return (char*)ins_addr + (offset * 4) + 8;
}
+#elif defined(TARGET_ARM64)
+ return mono_arch_get_call_target (((guint8*)ins_addr) + 4);
#else
g_assert_not_reached ();
return NULL;
align_int64 = align;
}
#else
- align_double = __alignof__ (double);
- align_int64 = __alignof__ (gint64);
+ align_double = MONO_ABI_ALIGNOF (double);
+ align_int64 = MONO_ABI_ALIGNOF (gint64);
#endif
/* Sanity check */
amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
amodule->blob = blob;
+ InitializeCriticalSection (&amodule->mutex);
+
/* Read image table */
{
guint32 table_len, i;
amodule->trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = info->gsharedvt_arg_trampolines;
amodule->thumb_end = info->thumb_end;
-#ifdef MONOTOUCH
if (info->flags & MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES) {
/* Compute code_offsets from the method addresses */
amodule->code_offsets = g_malloc0 (amodule->info.nmethods * sizeof (gint32));
for (i = 0; i < amodule->info.nmethods; ++i) {
/* method_addresses () contains a table of branches, since the ios linker can update those correctly */
- void *addr = get_arm_bl_target ((guint32*)amodule->method_addresses + i);
+ void *addr = NULL;
+#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+ addr = get_arm_bl_target ((guint32*)amodule->method_addresses + i);
+#elif defined(TARGET_X86) || defined(TARGET_AMD64)
+ addr = mono_arch_get_call_target ((guint8*)amodule->method_addresses + (i * 5) + 5);
+#else
+ g_assert_not_reached ();
+#endif
+ g_assert (addr);
if (addr == amodule->method_addresses)
amodule->code_offsets [i] = 0xffffffff;
else
amodule->code_offsets [i] = (char*)addr - (char*)amodule->code;
}
}
-#endif
if (make_unreadable) {
#ifndef TARGET_WIN32
if (!amodule || !amodule->class_name_table)
return FALSE;
- mono_aot_lock ();
+ amodule_lock (amodule);
*klass = NULL;
if (nspace_table) {
*klass = g_hash_table_lookup (nspace_table, name);
if (*klass) {
- mono_aot_unlock ();
+ amodule_unlock (amodule);
return TRUE;
}
}
name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) {
- mono_aot_unlock ();
+ amodule_unlock (amodule);
*klass = mono_class_get (image, token);
/* Add to cache */
if (*klass) {
- mono_aot_lock ();
+ amodule_lock (amodule);
nspace_table = g_hash_table_lookup (amodule->name_cache, name_space);
if (!nspace_table) {
nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (amodule->name_cache, (char*)name_space2, nspace_table);
}
g_hash_table_insert (nspace_table, (char*)name2, *klass);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
}
return TRUE;
}
}
}
- mono_aot_unlock ();
+ amodule_unlock (amodule);
return TRUE;
}
jinfo->from_aot = 1;
}
+ /*
+ * Set all the 'has' flags, the mono_jit_info_get () functions depends on this to
+ * compute the addresses of data blocks.
+ */
+ if (has_generic_jit_info)
+ jinfo->has_generic_jit_info = 1;
+ if (has_arch_eh_jit_info)
+ jinfo->has_arch_eh_info = 1;
+ if (has_try_block_holes)
+ jinfo->has_try_block_holes = 1;
+
if (has_try_block_holes) {
MonoTryBlockHoleTableJitInfo *table;
- jinfo->has_try_block_holes = 1;
+ g_assert (jinfo->has_try_block_holes);
table = mono_jit_info_get_try_block_hole_table_info (jinfo);
g_assert (table);
if (has_arch_eh_jit_info) {
MonoArchEHJitInfo *eh_info;
- jinfo->has_arch_eh_info = 1;
+ g_assert (jinfo->has_arch_eh_info);
eh_info = mono_jit_info_get_arch_eh_info (jinfo);
eh_info->stack_size = decode_value (p, &p);
MonoGenericJitInfo *gi;
int len;
- jinfo->has_generic_jit_info = 1;
+ g_assert (jinfo->has_generic_jit_info);
gi = mono_jit_info_get_generic_jit_info (jinfo);
g_assert (gi);
mono_aot_unlock ();
}
- p = amodule->unwind_info + ji->used_regs;
+ /* The upper 16 bits of ji->used_regs might contain the epilog offset */
+ p = amodule->unwind_info + (ji->used_regs & 0xffff);
*unwind_info_len = decode_value (p, &p);
return p;
}
MonoJitInfo *jinfo;
guint8 *code, *ex_info, *p;
guint32 *table;
- int nmethods = amodule->info.nmethods;
+ int nmethods;
gint32 *code_offsets;
int offsets_len, i;
gboolean async;
if (!amodule)
return NULL;
+ nmethods = amodule->info.nmethods;
+
if (domain != mono_get_root_domain ())
/* FIXME: */
return NULL;
/* Might be a wrapper/extra method */
if (!async) {
if (amodule->extra_methods) {
- mono_aot_lock ();
+ amodule_lock (amodule);
method = g_hash_table_lookup (amodule->extra_methods, GUINT_TO_POINTER (method_index));
- mono_aot_unlock ();
+ amodule_unlock (amodule);
} else {
method = NULL;
}
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
+ case MONO_PATCH_INFO_CLASS_INIT:
/* Shared */
ji->data.klass = decode_klass_ref (aot_module, p, &p);
if (!ji->data.klass)
goto cleanup;
break;
- case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
- ji->data.klass = decode_klass_ref (aot_module, p, &p);
- if (!ji->data.klass)
+ ji->data.del_tramp = mono_mempool_alloc0 (mp, sizeof (MonoClassMethodPair));
+ ji->data.del_tramp->klass = decode_klass_ref (aot_module, p, &p);
+ if (!ji->data.del_tramp->klass)
goto cleanup;
+ if (decode_value (p, &p)) {
+ ji->data.del_tramp->method = decode_resolve_method_ref (aot_module, p, &p);
+ if (!ji->data.del_tramp->method)
+ goto cleanup;
+ }
break;
case MONO_PATCH_INFO_IMAGE:
ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
code = &amodule->code [amodule->code_offsets [method_index] + 1];
}
- mono_aot_lock ();
- if (!amodule->methods_loaded)
- amodule->methods_loaded = g_new0 (guint32, amodule->info.nmethods / 32 + 1);
- mono_aot_unlock ();
+ if (!amodule->methods_loaded) {
+ amodule_lock (amodule);
+ if (!amodule->methods_loaded) {
+ guint32 *loaded;
+
+ loaded = g_new0 (guint32, amodule->info.nmethods / 32 + 1);
+ mono_memory_barrier ();
+ amodule->methods_loaded = loaded;
+ }
+ amodule_unlock (amodule);
+ }
if ((amodule->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
return code;
method = mono_get_method (image, token, NULL);
if (method) {
char *name = mono_method_full_name (method, TRUE);
- printf ("LAST AOT METHOD: %s.\n", name);
+ g_print ("LAST AOT METHOD: %s.\n", name);
g_free (name);
} else {
- printf ("LAST AOT METHOD: %p %d\n", code, method_index);
+ g_print ("LAST AOT METHOD: %p %d\n", code, method_index);
}
}
}
g_free (full_name);
}
- mono_aot_lock ();
+ amodule_lock (amodule);
InterlockedIncrement (&mono_jit_stats.methods_aot);
if (method && method->wrapper_type)
g_hash_table_insert (amodule->method_to_code, method, code);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) {
MonoJitInfo *jinfo;
p = amodule->blob + key;
orig_p = p;
- mono_aot_lock ();
+ amodule_lock (amodule);
if (!amodule->method_ref_to_method)
amodule->method_ref_to_method = g_hash_table_new (NULL, NULL);
m = g_hash_table_lookup (amodule->method_ref_to_method, p);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
if (!m) {
m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
if (m) {
- mono_aot_lock ();
+ amodule_lock (amodule);
g_hash_table_insert (amodule->method_ref_to_method, orig_p, m);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
}
}
if (m == method) {
method_index = mono_metadata_token_index (method->token) - 1;
} 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 */
- mono_aot_lock ();
+ amodule_lock (amodule);
code = g_hash_table_lookup (amodule->method_to_code, method);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
if (code)
return code;
return NULL;
/* Needed by find_jit_info */
- mono_aot_lock ();
+ 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);
- mono_aot_unlock ();
+ amodule_unlock (amodule);
} else {
/* Common case */
method_index = mono_metadata_token_index (method->token) - 1;
}
void
-mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr)
{
+ MonoAotModule *amodule;
+
/*
* Since AOT code is only used in the root domain,
* mono_domain_get () != mono_get_root_domain () means the calling method
* is AppDomain:InvokeInDomain, so this is the same check as in
* mono_method_same_domain () but without loading the metadata for the method.
*/
- if (mono_domain_get () == mono_get_root_domain ())
- mono_arch_patch_plt_entry (code, got, regs, addr);
+ if (mono_domain_get () == mono_get_root_domain ()) {
+ if (!got) {
+ amodule = find_aot_module (code);
+ if (amodule)
+ got = amodule->got;
+ }
+ mono_arch_patch_plt_entry (plt_entry, got, regs, addr);
+ }
}
/*
/* Patch the PLT entry with target which might be the actual method not a trampoline */
plt_entry = mono_aot_get_plt_entry (code);
g_assert (plt_entry);
- mono_aot_patch_plt_entry (plt_entry, module->got, NULL, target);
+ mono_aot_patch_plt_entry (code, plt_entry, module->got, NULL, target);
return target;
#else
*
* Initialize the PLT table of the AOT module. Called lazily when the first AOT
* method in the module is loaded to avoid committing memory by writing to it.
- * LOCKING: Assumes the AOT lock is held.
+ * LOCKING: Assumes the AMODULE lock is held.
*/
static void
init_plt (MonoAotModule *amodule)
page = (TrampolinePage*)addr;
page->next = trampoline_pages [tramp_type];
trampoline_pages [tramp_type] = page;
+#ifdef TARGET_ARM64
+ page->trampolines = (void*)(taddr + amodule->info.tramp_page_code_offsets [tramp_type]);
+#else
page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]);
- page->trampolines_end = (void*)(taddr + psize);
+#endif
+ page->trampolines_end = (void*)(taddr + psize - 64);
code = page->trampolines;
- page->trampolines += 8;
+ page->trampolines += specific_trampoline_size;
mono_aot_page_unlock ();
return code;
}
}
void
-mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr)
{
}