Emit proper unwind info for the gsharedvt trampoline in full-aot mode. Fix gsharedvt...
authorZoltan Varga <vargaz@gmail.com>
Tue, 29 Jan 2013 00:59:19 +0000 (01:59 +0100)
committerZoltan Varga <vargaz@gmail.com>
Tue, 29 Jan 2013 01:01:17 +0000 (02:01 +0100)
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/mini.c
mono/mini/mini.h

index 2da5ee564cc4e1b6c3b30ca2041477995a659fe8..c802015ea14aaea78b35915a5f57d3ca243e58de 100644 (file)
@@ -127,6 +127,7 @@ typedef struct MonoAotOptions {
        gboolean direct_icalls;
        gboolean no_direct_calls;
        gboolean use_trampolines_page;
+       gboolean no_instances;
        int nthreads;
        int ntrampolines;
        int nrgctx_trampolines;
@@ -1285,7 +1286,7 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *
        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;
@@ -3685,6 +3686,9 @@ add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int
        MonoGenericContext ctx;
        MonoType *args [16];
 
+       if (acfg->aot_opts.no_instances)
+               return;
+
        memset (&ctx, 0, sizeof (ctx));
 
        for (i = 0; i < ninsts; ++i) {
@@ -3733,6 +3737,9 @@ add_generic_instances (MonoAotCompile *acfg)
        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);
@@ -5120,10 +5127,17 @@ emit_plt (MonoAotCompile *acfg)
        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;
@@ -5165,6 +5179,11 @@ emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *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 */
@@ -5191,6 +5210,22 @@ emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
 
        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];
@@ -5203,6 +5238,12 @@ emit_trampoline (MonoAotCompile *acfg, int got_offset, MonoTrampInfo *info)
        }
 }
 
+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)
 {
@@ -5263,7 +5304,7 @@ 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)
@@ -5564,6 +5605,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        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=")) {
@@ -5601,6 +5644,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        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");
@@ -5868,7 +5912,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
         * 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: {
index f762d16c352715ecc4aadf1834918759079de040..04d6f2a4cc170a4728e397d8f30d05cc99017ff8 100644 (file)
@@ -3603,6 +3603,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
        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);
 
@@ -3618,6 +3619,10 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
                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.
@@ -3625,7 +3630,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
         * 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 {
@@ -3795,18 +3800,19 @@ mono_aot_register_jit_icall (const char *name, gpointer addr)
 }
 
 /*
- * 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 */
 
@@ -3827,7 +3833,30 @@ load_function (MonoAotModule *amodule, const char *name)
                /* 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 () */
 
@@ -3914,12 +3943,18 @@ load_function (MonoAotModule *amodule, const char *name)
        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;
@@ -3930,7 +3965,13 @@ mono_aot_get_trampoline (const char *name)
        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
index 948507d96741b4c1ff80c212652383fbdbd7a237..9a5192b6223ecda060e859c2fe40f016c039be49 100644 (file)
@@ -3929,7 +3929,12 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
        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;
@@ -5521,15 +5526,13 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                         * 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;
                }
        }
 
index aa5ea7879adb3e22927020c8f12589968c3cb79f..7ea0a104cf0f5bf9c28145ad5c20fef49acb632d 100644 (file)
@@ -1771,6 +1771,12 @@ enum {
         * 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);
@@ -1947,6 +1953,7 @@ void     mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, g
 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;