/* The first unused trampoline of each kind */
guint32 trampoline_index [MONO_AOT_TRAMP_NUM];
+ gboolean use_page_trampolines;
+
MonoAotFileInfo info;
gpointer *globals;
MonoDl *sofile;
} MonoAotModule;
+typedef struct {
+ void *next;
+ unsigned char *trampolines;
+ unsigned char *trampolines_end;
+} TrampolinePage;
+
static GHashTable *aot_modules;
#define mono_aot_lock() EnterCriticalSection (&aot_mutex)
#define mono_aot_unlock() LeaveCriticalSection (&aot_mutex)
static GHashTable *aot_jit_icall_hash;
+#ifdef MONOTOUCH
+#define USE_PAGE_TRAMPOLINES ((MonoAotModule*)mono_defaults.corlib->aot_module)->use_page_trampolines
+#else
+#define USE_PAGE_TRAMPOLINES 0
+#endif
+
+#define mono_aot_page_lock() EnterCriticalSection (&aot_page_mutex)
+#define mono_aot_page_unlock() LeaveCriticalSection (&aot_page_mutex)
+static CRITICAL_SECTION aot_page_mutex;
+
static void
init_plt (MonoAotModule *info);
class_def = decode_klass_ref (module, p, &p);
if (!class_def)
return NULL;
-
+
container = class_def->generic_container;
}
} else {
// FIXME: Memory management
t = g_new0 (MonoType, 1);
t->type = type;
-
if (container) {
t->data.generic_param = mono_generic_container_get_param (container, num);
g_assert (serial == 0);
t->data.array = array;
break;
}
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR: {
+ MonoClass *klass = decode_klass_ref (module, p, &p);
+ if (!klass)
+ return NULL;
+ t->data.generic_param = klass->byval_arg.data.generic_param;
+ break;
+ }
default:
g_assert_not_reached ();
}
{
MonoMethodSignature *sig;
guint32 flags;
- int i, param_count, call_conv;
+ int i, param_count, call_conv, gen_param_count = 0;
guint8 *p = buf;
gboolean hasthis, explicit_this, has_gen_params;
explicit_this = (flags & 0x40) != 0;
call_conv = flags & 0x0F;
- g_assert (!has_gen_params);
-
+ if (has_gen_params)
+ gen_param_count = decode_value (p, &p);
param_count = decode_value (p, &p);
if (target && param_count != target->param_count)
return NULL;
image = mono_defaults.corlib;
switch (wrapper_type) {
+#ifndef DISABLE_REMOTING
case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
MonoMethod *m = decode_resolve_method_ref (module, p, &p);
case MONO_WRAPPER_STFLD_REMOTE:
ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
break;
+#endif
case MONO_WRAPPER_ALLOC: {
int atype = decode_value (p, &p);
if (!m)
return FALSE;
ref->method = mono_marshal_get_synchronized_inner_wrapper (m);
+ } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN) {
+ ref->method = mono_marshal_get_gsharedvt_in_wrapper ();
+ } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
+ ref->method = mono_marshal_get_gsharedvt_out_wrapper ();
} else {
if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER)
desc = mono_method_desc_new ("Monitor:Enter", FALSE);
}
break;
}
- case MONO_WRAPPER_DELEGATE_INVOKE:
+ case MONO_WRAPPER_DELEGATE_INVOKE: {
+ gboolean is_inflated = decode_value (p, &p);
+
+ if (is_inflated) {
+ MonoClass *klass;
+ MonoMethod *invoke, *wrapper;
+
+ klass = decode_klass_ref (module, p, &p);
+ if (!klass)
+ return FALSE;
+ invoke = mono_get_delegate_invoke (klass);
+ wrapper = mono_marshal_get_delegate_invoke (invoke, NULL);
+ if (target && wrapper != target)
+ return FALSE;
+ ref->method = wrapper;
+ break;
+ } else {
+ /* Fall through */
+ }
+ }
case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
case MONO_WRAPPER_DELEGATE_END_INVOKE: {
/*
g_assert_not_reached ();
}
} else {
- g_assert (image_index < MONO_AOT_METHODREF_MIN);
+ if (image_index == MONO_AOT_METHODREF_LARGE_IMAGE_INDEX) {
+ image_index = decode_value (p, &p);
+ value = decode_value (p, &p);
+ }
+
ref->token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
image = load_image (module, image_index, TRUE);
guint16 *table, *entry;
guint16 table_size;
guint32 hash;
+ char *symbol = (char*)name;
+
+#ifdef TARGET_MACH
+ symbol = g_strdup_printf ("_%s", name);
+#endif
/* The first entry points to the hash */
table = globals [0];
table_size = table [0];
table ++;
- hash = mono_metadata_str_hash (name) % table_size;
+ hash = mono_metadata_str_hash (symbol) % table_size;
entry = &table [hash * 2];
//printf ("X: %s %s\n", (char*)globals [index * 2], name);
- if (!strcmp (globals [index * 2], name)) {
+ if (!strcmp (globals [index * 2], symbol)) {
global_index = index;
break;
}
*value = globals [global_index * 2 + 1];
else
*value = NULL;
+
+ if (symbol != name)
+ g_free (symbol);
} else {
char *err = mono_dl_symbol (module, name, value);
amodule->trampolines [MONO_AOT_TRAMP_SPECIFIC] = info->specific_trampolines;
amodule->trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = info->static_rgctx_trampolines;
amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK] = info->imt_thunks;
+ amodule->trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = info->gsharedvt_arg_trampolines;
amodule->thumb_end = info->thumb_end;
#ifdef MONOTOUCH
assembly->image->aot_module = amodule;
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;
mono_aot_init (void)
{
InitializeCriticalSection (&aot_mutex);
+ InitializeCriticalSection (&aot_page_mutex);
aot_modules = g_hash_table_new (NULL, NULL);
mono_install_assembly_load_hook (load_aot_module, NULL);
}
}
- /* This currently contains no data */
- gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
-
jinfo->method = decode_resolve_method_ref (amodule, p, &p);
+
+ gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
+ if (decode_value (p, &p)) {
+ /* gsharedvt */
+ int i, n;
+ MonoGenericSharingContext *gsctx = gi->generic_sharing_context;
+
+ n = decode_value (p, &p);
+ if (n) {
+ gsctx->var_is_vt = g_new0 (gboolean, n);
+ for (i = 0; i < n; ++i)
+ gsctx->var_is_vt [i] = decode_value (p, &p);
+ }
+ n = decode_value (p, &p);
+ if (n) {
+ gsctx->mvar_is_vt = g_new0 (gboolean, n);
+ for (i = 0; i < n; ++i)
+ gsctx->mvar_is_vt [i] = decode_value (p, &p);
+ }
+ }
}
if (has_try_block_holes) {
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_CASTCLASS_CACHE:
+ case MONO_PATCH_INFO_JIT_TLS_ID:
break;
case MONO_PATCH_INFO_RGCTX_FETCH: {
gboolean res;
case MONO_PATCH_INFO_SIGNATURE:
ji->data.target = decode_signature (aot_module, p, &p);
break;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL: {
+ MonoJumpInfoGSharedVtCall *info = g_new0 (MonoJumpInfoGSharedVtCall, 1);
+ info->sig = decode_signature (aot_module, p, &p);
+ g_assert (info->sig);
+ info->method = decode_resolve_method_ref (aot_module, p, &p);
+ g_assert (info->method);
+
+ ji->data.target = info;
+ break;
+ }
default:
g_warning ("unhandled type %d", ji->type);
g_assert_not_reached ();
if (!method)
method = mono_get_method (image, token, NULL);
full_name = mono_method_full_name (method, TRUE);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.", full_name);
g_free (full_name);
}
return NULL;
if (!jinfo)
jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND method %s [%p - %p %p]\n", full_name, code, code + jinfo->code_size, info);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND method %s [%p - %p %p]", full_name, code, code + jinfo->code_size, info);
g_free (full_name);
}
}
static guint32
-find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, const char *name)
+find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method)
{
guint32 table_size, entry_size, hash;
guint32 *table, *entry;
guint32 index;
GPtrArray *modules;
int i;
- char *name = NULL;
-
- if (method->wrapper_type)
- name = mono_aot_wrapper_name (method);
/* Try the method's module first */
*out_amodule = method->klass->image->aot_module;
- index = find_extra_method_in_amodule (method->klass->image->aot_module, method, name);
- if (index != 0xffffff) {
- g_free (name);
+ index = find_extra_method_in_amodule (method->klass->image->aot_module, method);
+ if (index != 0xffffff)
return index;
- }
/*
* Try all other modules.
MonoAotModule *amodule = g_ptr_array_index (modules, i);
if (amodule != method->klass->image->aot_module)
- index = find_extra_method_in_amodule (amodule, method, name);
+ index = find_extra_method_in_amodule (amodule, method);
if (index != 0xffffff) {
*out_amodule = amodule;
break;
g_ptr_array_free (modules, TRUE);
- g_free (name);
return index;
}
g_assert (klass->inited);
/* Find method index */
- if (method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) {
+ if (method->is_inflated && !method->wrapper_type && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) {
/*
* For generic methods, we store the fully shared instance in place of the
* original method.
return code;
}
- if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, TRUE)) {
- /* Partial sharing */
- method_index = find_extra_method (mini_get_shared_method (method), &amodule);
+ if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE)) {
+ /* gsharedvt */
+ /* Use the all-vt shared method since this is what was AOTed */
+ method_index = find_extra_method (mini_get_shared_method_full (method, TRUE, TRUE), &amodule);
+ if (method_index != 0xffffff)
+ method = mini_get_shared_method_full (method, TRUE, FALSE);
}
if (method_index == 0xffffff) {
MonoAotModule *module = (MonoAotModule*)aot_module;
gboolean res, no_ftnptr = FALSE;
MonoMemPool *mp;
+ gboolean using_gsharedvt = FALSE;
//printf ("DYN: %p %d\n", aot_module, plt_info_offset);
return NULL;
}
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+ using_gsharedvt = TRUE;
+#endif
+
/*
* Avoid calling resolve_patch_target in the full-aot case if possible, since
* it would create a trampoline, and we don't need that.
* in mono_magic_trampoline ().
*/
if (mono_aot_only && ji.type == MONO_PATCH_INFO_METHOD && !ji.data.method->is_generic && !mono_method_check_context_used (ji.data.method) && !(ji.data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) &&
- !mono_method_needs_static_rgctx_invoke (ji.data.method, FALSE)) {
+ !mono_method_needs_static_rgctx_invoke (ji.data.method, FALSE) && !using_gsharedvt) {
target = mono_jit_compile_method (ji.data.method);
no_ftnptr = TRUE;
} else {
}
/*
- * load_function:
+ * load_function_full:
*
* Load the function named NAME from the aot image.
*/
static gpointer
-load_function (MonoAotModule *amodule, const char *name)
+load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **out_tinfo)
{
char *symbol;
guint8 *p;
int n_patches, pindex;
MonoMemPool *mp;
gpointer code;
+ guint32 info_offset;
/* Load the code */
if (!code)
g_error ("Symbol '%s' not found in AOT file '%s'.\n", name, amodule->aot_name);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND function '%s' in AOT file '%s'.\n", name, amodule->aot_name);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND function '%s' in AOT file '%s'.", name, amodule->aot_name);
/* Load info */
/* Nothing to patch */
return code;
- p = amodule->blob + *(guint32*)p;
+ info_offset = *(guint32*)p;
+ if (out_tinfo) {
+ MonoTrampInfo *tinfo;
+ guint32 code_size, uw_info_len, uw_offset;
+ guint8 *uw_info;
+ /* Construct a MonoTrampInfo from the data in the AOT image */
+
+ p += sizeof (guint32);
+ code_size = *(guint32*)p;
+ p += sizeof (guint32);
+ uw_offset = *(guint32*)p;
+ uw_info = amodule->unwind_info + uw_offset;
+ uw_info_len = decode_value (uw_info, &uw_info);
+
+ tinfo = g_new0 (MonoTrampInfo, 1);
+ tinfo->code = code;
+ tinfo->code_size = code_size;
+ tinfo->uw_info = uw_info;
+ tinfo->uw_info_len = uw_info_len;
+
+ *out_tinfo = tinfo;
+ }
+
+ p = amodule->blob + info_offset;
/* Similar to mono_aot_load_method () */
return code;
}
+static gpointer
+load_function (MonoAotModule *amodule, const char *name)
+{
+ return load_function_full (amodule, name, NULL);
+}
+
/*
* Return the trampoline identified by NAME from the mscorlib AOT file.
* On ppc64, this returns a function descriptor.
*/
gpointer
-mono_aot_get_trampoline (const char *name)
+mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
{
MonoImage *image;
MonoAotModule *amodule;
amodule = image->aot_module;
g_assert (amodule);
- return mono_create_ftnptr_malloc (load_function (amodule, name));
+ return mono_create_ftnptr_malloc (load_function_full (amodule, name, out_tinfo));
+}
+
+gpointer
+mono_aot_get_trampoline (const char *name)
+{
+ return mono_aot_get_trampoline_full (name, NULL);
+}
+
+#ifdef MONOTOUCH
+#include <mach/mach.h>
+
+static TrampolinePage* trampoline_pages [MONO_AOT_TRAMP_NUM];
+/* these sizes are for ARM code, parametrize if porting to other architectures (see arch_emit_specific_trampoline_pages)
+ * trampoline size is assumed to be 8 bytes below as well (8 is the minimum for 32 bit archs, since we need to store
+ * two pointers for trampoline in the data page).
+ * the minimum for the common code must be at least sizeof(TrampolinePage), since we store the page info at the
+ * beginning of the data page.
+ */
+static const int trampolines_pages_code_offsets [MONO_AOT_TRAMP_NUM] = {16, 16, 72, 16};
+
+static unsigned char*
+get_new_trampoline_from_page (int tramp_type)
+{
+ MonoAotModule *amodule;
+ MonoImage *image;
+ TrampolinePage *page;
+ int count;
+ void *tpage;
+ vm_address_t addr, taddr;
+ kern_return_t ret;
+ vm_prot_t prot, max_prot;
+ int psize;
+ unsigned char *code;
+
+ mono_aot_page_lock ();
+ page = trampoline_pages [tramp_type];
+ if (page && page->trampolines < page->trampolines_end) {
+ code = page->trampolines;
+ page->trampolines += 8;
+ mono_aot_page_unlock ();
+ return code;
+ }
+ mono_aot_page_unlock ();
+ psize = mono_pagesize ();
+ /* the trampoline template page is in the mscorlib module */
+ image = mono_defaults.corlib;
+ g_assert (image);
+
+ amodule = image->aot_module;
+ g_assert (amodule);
+
+ if (tramp_type == MONO_AOT_TRAMP_SPECIFIC)
+ tpage = load_function (amodule, "specific_trampolines_page");
+ else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
+ tpage = load_function (amodule, "rgctx_trampolines_page");
+ else if (tramp_type == MONO_AOT_TRAMP_IMT_THUNK)
+ tpage = load_function (amodule, "imt_trampolines_page");
+ else if (tramp_type == MONO_AOT_TRAMP_GSHAREDVT_ARG)
+ tpage = load_function (amodule, "gsharedvt_arg_trampolines_page");
+ else
+ g_error ("Incorrect tramp type for trampolines page");
+ g_assert (tpage);
+ /*g_warning ("loaded trampolines page at %x", tpage);*/
+
+ /* avoid the unlikely case of looping forever */
+ count = 40;
+ page = NULL;
+ while (page == NULL && count-- > 0) {
+ addr = 0;
+ /* allocate two contiguous pages of memory: the first page will contain the data (like a local constant pool)
+ * while the second will contain the trampolines.
+ */
+ ret = vm_allocate (mach_task_self (), &addr, psize * 2, VM_FLAGS_ANYWHERE);
+ if (ret != KERN_SUCCESS) {
+ g_error ("Cannot allocate memory for trampolines: %d", ret);
+ break;
+ }
+ /*g_warning ("allocated trampoline double page at %x", addr);*/
+ /* replace the second page with a remapped trampoline page */
+ taddr = addr + psize;
+ vm_deallocate (mach_task_self (), taddr, psize);
+ ret = vm_remap (mach_task_self (), &taddr, psize, 0, FALSE, mach_task_self(), (vm_address_t)tpage, FALSE, &prot, &max_prot, VM_INHERIT_SHARE);
+ if (ret != KERN_SUCCESS) {
+ /* someone else got the page, try again */
+ vm_deallocate (mach_task_self (), addr, psize);
+ continue;
+ }
+ /*g_warning ("remapped trampoline page at %x", taddr);*/
+
+ mono_aot_page_lock ();
+ page = trampoline_pages [tramp_type];
+ /* some other thread already allocated, so use that to avoid wasting memory */
+ if (page && page->trampolines < page->trampolines_end) {
+ code = page->trampolines;
+ page->trampolines += 8;
+ mono_aot_page_unlock ();
+ vm_deallocate (mach_task_self (), addr, psize);
+ vm_deallocate (mach_task_self (), taddr, psize);
+ return code;
+ }
+ page = (TrampolinePage*)addr;
+ page->next = trampoline_pages [tramp_type];
+ trampoline_pages [tramp_type] = page;
+ page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]);
+ page->trampolines_end = (void*)(taddr + psize);
+ code = page->trampolines;
+ page->trampolines += 8;
+ mono_aot_page_unlock ();
+ return code;
+ }
+ g_error ("Cannot allocate more trampoline pages: %d", ret);
+ return NULL;
+}
+
+#else
+static unsigned char*
+get_new_trampoline_from_page (int tramp_type)
+{
+ g_error ("Page trampolines not supported.");
+ return NULL;
+}
+#endif
+
+
+static gpointer
+get_new_specific_trampoline_from_page (gpointer tramp, gpointer arg)
+{
+ void *code;
+ gpointer *data;
+
+ code = get_new_trampoline_from_page (MONO_AOT_TRAMP_SPECIFIC);
+
+ data = (gpointer*)((char*)code - mono_pagesize ());
+ data [0] = arg;
+ data [1] = tramp;
+ /*g_warning ("new trampoline at %p for data %p, tramp %p (stored at %p)", code, arg, tramp, data);*/
+ return code;
+
+}
+
+static gpointer
+get_new_rgctx_trampoline_from_page (gpointer tramp, gpointer arg)
+{
+ void *code;
+ gpointer *data;
+
+ code = get_new_trampoline_from_page (MONO_AOT_TRAMP_STATIC_RGCTX);
+
+ data = (gpointer*)((char*)code - mono_pagesize ());
+ data [0] = arg;
+ data [1] = tramp;
+ /*g_warning ("new rgctx trampoline at %p for data %p, tramp %p (stored at %p)", code, arg, tramp, data);*/
+ return code;
+
+}
+
+static gpointer
+get_new_imt_trampoline_from_page (gpointer arg)
+{
+ void *code;
+ gpointer *data;
+
+ code = get_new_trampoline_from_page (MONO_AOT_TRAMP_IMT_THUNK);
+
+ data = (gpointer*)((char*)code - mono_pagesize ());
+ data [0] = arg;
+ /*g_warning ("new imt trampoline at %p for data %p, (stored at %p)", code, arg, data);*/
+ return code;
+
+}
+
+static gpointer
+get_new_gsharedvt_arg_trampoline_from_page (gpointer tramp, gpointer arg)
+{
+ void *code;
+ gpointer *data;
+
+ code = get_new_trampoline_from_page (MONO_AOT_TRAMP_GSHAREDVT_ARG);
+
+ data = (gpointer*)((char*)code - mono_pagesize ());
+ data [0] = arg;
+ data [1] = tramp;
+ /*g_warning ("new rgctx trampoline at %p for data %p, tramp %p (stored at %p)", code, arg, tramp, data);*/
+ return code;
}
/* Return a given kind of trampoline */
*out_amodule = amodule;
- if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type]) {
- g_error ("Ran out of trampolines of type %d in '%s' (%d)%s\n",
- tramp_type, image->name, amodule->info.num_trampolines [tramp_type],
#ifdef MONOTOUCH
- ". See http://docs.xamarin.com/ios/troubleshooting for instruction on how to fix this condition"
+#define MONOTOUCH_TRAMPOLINES_ERROR ". See http://docs.xamarin.com/ios/troubleshooting for instruction on how to fix this condition"
#else
- ""
+#define MONOTOUCH_TRAMPOLINES_ERROR ""
#endif
- );
+ if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type]) {
+ g_error ("Ran out of trampolines of type %d in '%s' (%d)%s\n",
+ tramp_type, image->name, amodule->info.num_trampolines [tramp_type], MONOTOUCH_TRAMPOLINES_ERROR);
}
index = amodule->trampoline_index [tramp_type] ++;
tramp = generic_trampolines [tramp_type];
g_assert (tramp);
- code = get_numerous_trampoline (MONO_AOT_TRAMP_SPECIFIC, 2, &amodule, &got_offset, &tramp_size);
+ if (USE_PAGE_TRAMPOLINES) {
+ code = get_new_specific_trampoline_from_page (tramp, arg1);
+ tramp_size = 8;
+ } else {
+ code = get_numerous_trampoline (MONO_AOT_TRAMP_SPECIFIC, 2, &amodule, &got_offset, &tramp_size);
- amodule->got [got_offset] = tramp;
- amodule->got [got_offset + 1] = arg1;
+ amodule->got [got_offset] = tramp;
+ amodule->got [got_offset + 1] = arg1;
+ }
if (code_len)
*code_len = tramp_size;
guint8 *code;
guint32 got_offset;
- code = get_numerous_trampoline (MONO_AOT_TRAMP_STATIC_RGCTX, 2, &amodule, &got_offset, NULL);
+ if (USE_PAGE_TRAMPOLINES) {
+ code = get_new_rgctx_trampoline_from_page (addr, ctx);
+ } else {
+ code = get_numerous_trampoline (MONO_AOT_TRAMP_STATIC_RGCTX, 2, &amodule, &got_offset, NULL);
- amodule->got [got_offset] = ctx;
- amodule->got [got_offset + 1] = addr;
+ amodule->got [got_offset] = ctx;
+ amodule->got [got_offset + 1] = addr;
+ }
/* The caller expects an ftnptr */
return mono_create_ftnptr (mono_domain_get (), code);
guint32 *ut, *ut_end, *entry;
int low, high, entry_index;
- if (method->is_inflated && !mono_method_is_generic_sharable_impl (method, FALSE)) {
+ if (method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) {
method_index = find_extra_method (method, &amodule);
+ if (method_index == 0xffffff && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE)) {
+ MonoMethod *shared = mini_get_shared_method_full (method, TRUE, TRUE);
+ method_index = find_extra_method (shared, &amodule);
+ }
g_assert (method_index != 0xffffff);
} else {
amodule = method->klass->image->aot_module;
} else if (entry [0] > method_index) {
high = entry_index;
} else {
- code = amodule->code + entry [1];
+ if (amodule->info.flags & MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES)
+ code = (gpointer)(gsize)entry [1];
+ else
+ code = amodule->code + entry [1];
break;
}
}
{
char *symbol;
gpointer code;
+ MonoAotModule *amodule = mono_defaults.corlib->aot_module;
+ guint32 index = MONO_RGCTX_SLOT_INDEX (slot);
+ static int count = 0;
+
+ count ++;
+ if (index >= amodule->info.num_rgctx_fetch_trampolines) {
+ static gpointer addr;
+ gpointer *info;
+
+ /*
+ * Use the general version of the rgctx fetch trampoline. It receives a pair of <slot, trampoline> in the rgctx arg reg.
+ */
+ if (!addr)
+ addr = load_function (amodule, "rgctx_fetch_trampoline_general");
+ info = mono_domain_alloc0 (mono_get_root_domain (), sizeof (gpointer) * 2);
+ info [0] = GUINT_TO_POINTER (slot);
+ info [1] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
+ code = mono_aot_get_static_rgctx_trampoline (info, addr);
+ return mono_create_ftnptr (mono_domain_get (), code);
+ }
symbol = mono_get_rgctx_fetch_trampoline_name (slot);
code = load_function (mono_defaults.corlib->aot_module, symbol);
int i, index, real_count;
MonoAotModule *amodule;
- code = get_numerous_trampoline (MONO_AOT_TRAMP_IMT_THUNK, 1, &amodule, &got_offset, NULL);
-
real_count = 0;
for (i = 0; i < count; ++i) {
MonoIMTCheckItem *item = imt_entries [i];
buf [(index * 2)] = NULL;
buf [(index * 2) + 1] = fail_tramp;
- amodule->got [got_offset] = buf;
+ if (USE_PAGE_TRAMPOLINES) {
+ code = get_new_imt_trampoline_from_page (buf);
+ } else {
+ code = get_numerous_trampoline (MONO_AOT_TRAMP_IMT_THUNK, 1, &amodule, &got_offset, NULL);
+
+ amodule->got [got_offset] = buf;
+ }
return code;
}
+
+gpointer
+mono_aot_get_gsharedvt_arg_trampoline (gpointer arg, gpointer addr)
+{
+ MonoAotModule *amodule;
+ guint8 *code;
+ guint32 got_offset;
+
+ if (USE_PAGE_TRAMPOLINES) {
+ code = get_new_gsharedvt_arg_trampoline_from_page (addr, arg);
+ } else {
+ code = get_numerous_trampoline (MONO_AOT_TRAMP_GSHAREDVT_ARG, 2, &amodule, &got_offset, NULL);
+
+ amodule->got [got_offset] = arg;
+ amodule->got [got_offset + 1] = addr;
+ }
+
+ /* The caller expects an ftnptr */
+ return mono_create_ftnptr (mono_domain_get (), code);
+}
/*
* mono_aot_set_make_unreadable: