gboolean direct_icalls;
gboolean no_direct_calls;
gboolean use_trampolines_page;
+ gboolean no_instances;
int nthreads;
int ntrampolines;
int nrgctx_trampolines;
guint8 *code;
if (acfg->thumb_mixed && cfg->compile_llvm) {
- fprintf (acfg->fp, "add r0, r0, #%d\n", sizeof (MonoObject));
+ fprintf (acfg->fp, "add r0, r0, #%d\n", (int)sizeof (MonoObject));
fprintf (acfg->fp, "b %s\n", call_target);
fprintf (acfg->fp, ".arm\n");
return;
MonoGenericContext ctx;
MonoType *args [16];
+ if (acfg->aot_opts.no_instances)
+ return;
+
memset (&ctx, 0, sizeof (ctx));
for (i = 0; i < ninsts; ++i) {
MonoMethod *method;
MonoGenericContext *context;
+ if (acfg->aot_opts.no_instances)
+ return;
+
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
token = MONO_TOKEN_METHOD_SPEC | (i + 1);
method = mono_get_method (acfg->image, token, NULL);
emit_label (acfg, symbol);
}
+/*
+ * emit_trampoline_full:
+ *
+ * If EMIT_TINFO is TRUE, emit additional information which can be used to create a MonoJitInfo for this trampoline by
+ * create_jit_info_for_trampoline ().
+ */
static G_GNUC_UNUSED void
-emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
+emit_trampoline_full (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info, gboolean emit_tinfo)
{
char start_symbol [256];
+ char end_symbol [256];
char symbol [256];
guint32 buf_size, info_offset;
MonoJumpInfo *patch_info;
emit_symbol_size (acfg, start_symbol, ".");
+ if (emit_tinfo) {
+ sprintf (end_symbol, "%snamede_%s", acfg->temp_prefix, name);
+ emit_label (acfg, end_symbol);
+ }
+
/* Emit info */
/* Sort relocations */
emit_int32 (acfg, info_offset);
+ if (emit_tinfo) {
+ guint8 *encoded;
+ guint32 encoded_len;
+ guint32 uw_offset;
+
+ /*
+ * Emit additional information which can be used to reconstruct a partial MonoTrampInfo.
+ */
+ encoded = mono_unwind_ops_encode (info->unwind_ops, &encoded_len);
+ uw_offset = get_unwind_info_offset (acfg, encoded, encoded_len);
+ g_free (encoded);
+
+ emit_symbol_diff (acfg, end_symbol, start_symbol, 0);
+ emit_int32 (acfg, uw_offset);
+ }
+
/* Emit debug info */
if (unwind_ops) {
char symbol2 [256];
}
}
+static G_GNUC_UNUSED void
+emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
+{
+ emit_trampoline_full (acfg, got_offset, info, FALSE);
+}
+
static void
emit_trampolines (MonoAotCompile *acfg)
{
#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
mono_arch_get_gsharedvt_trampoline (&info, TRUE);
- emit_trampoline (acfg, acfg->got_offset, info);
+ emit_trampoline_full (acfg, acfg->got_offset, info, TRUE);
#endif
#if defined(MONO_ARCH_HAVE_GET_TRAMPOLINES)
opts->print_skipped_methods = TRUE;
} else if (str_begins_with (arg, "stats")) {
opts->stats = TRUE;
+ } else if (str_begins_with (arg, "no-instances")) {
+ opts->no_instances = TRUE;
} else if (str_begins_with (arg, "log-generics")) {
opts->log_generics = TRUE;
} else if (str_begins_with (arg, "mtriple=")) {
printf (" soft-debug\n");
printf (" gc-maps\n");
printf (" print-skipped\n");
+ printf (" no-instances\n");
printf (" stats\n");
printf (" info\n");
printf (" help/?\n");
* encountered.
*/
depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
- if (depth < 32) {
+ if (!acfg->aot_opts.no_instances && depth < 32) {
for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
switch (patch_info->type) {
case MONO_PATCH_INFO_METHOD: {
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 */
/* 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
guint8 *uw_info;
guint32 info_len;
- uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
+ if (info->uw_info) {
+ uw_info = info->uw_info;
+ info_len = info->uw_info_len;
+ } else {
+ uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
+ }
jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
jinfo->method = wrapper;
* works.
* FIXME: The caller signature doesn't match the callee, which might cause problems on some platforms
*/
- if (mono_aot_only) {
- // FIXME: No EH
- return mono_aot_get_trampoline ("gsharedvt_trampoline");
- } else {
+ if (mono_aot_only)
+ mono_aot_get_trampoline_full ("gsharedvt_trampoline", &tinfo);
+ else
mono_arch_get_gsharedvt_trampoline (&tinfo, FALSE);
- jinfo = create_jit_info_for_trampoline (method, tinfo);
- mono_jit_info_table_add (mono_get_root_domain (), jinfo);
- return tinfo->code;
- }
+ jinfo = create_jit_info_for_trampoline (method, tinfo);
+ mono_jit_info_table_add (mono_get_root_domain (), jinfo);
+ return tinfo->code;
}
}
* Unwind information. Owned by this structure.
*/
GSList *unwind_ops;
+
+ /*
+ * Encoded unwind info loaded from AOT images
+ */
+ guint8 *uw_info;
+ guint32 uw_info_len;
} MonoTrampInfo;
typedef void (*MonoInstFunc) (MonoInst *tree, gpointer data);
gpointer mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot) MONO_INTERNAL;
gpointer mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL;
gpointer mono_aot_get_trampoline (const char *name) MONO_INTERNAL;
+gpointer mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo) MONO_INTERNAL;
gpointer mono_aot_get_unbox_trampoline (MonoMethod *method) MONO_INTERNAL;
gpointer mono_aot_get_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
gpointer mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr) MONO_INTERNAL;