2008-07-08 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Tue, 8 Jul 2008 19:57:52 +0000 (19:57 -0000)
committerZoltan Varga <vargaz@gmail.com>
Tue, 8 Jul 2008 19:57:52 +0000 (19:57 -0000)
* tramp-amd64.c (mono_arch_nullify_plt_entry): Read the nullified class
init trampoline from the AOT file as well.

* mini-amd64.c (mono_arch_register_lowlevel_calls): Register
mono_amd64_throw_exception as a jit icall since it is needed by the aot-only
code.

* mini.c (mini_init): Move the call to mono_exceptions_init () after
mono_init.

* exceptions-amd64.c: Add _full variants for the remaining exception code
creation functions as well, allow emission of relocatable code, remove
caching since that is now done by the caller.

* mini-exceptions.c: Add _full variants for the remaining exception code
creation functions as well, add aot-only support.

* aot-compiler.c (compile_method): Allow calls to methods of constructed types
if we can determine a proper token for them.
(add_wrappers): Add a few more wrappers.
(emit_method_code): Remove some dead code.
(emit_trampolines): Emit exception code too.

svn path=/trunk/mono/; revision=107487

mono/mini/ChangeLog
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/exceptions-amd64.c
mono/mini/mini-amd64.c
mono/mini/mini-exceptions.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/tramp-amd64.c

index db4441e86ebf523d1ff2031d329f86c77aba0bd6..4a7b17c2b3cd9ff7fa175f3948a9b20dc4a358a2 100644 (file)
@@ -1,5 +1,28 @@
 2008-07-08  Zoltan Varga  <vargaz@gmail.com>
 
+       * tramp-amd64.c (mono_arch_nullify_plt_entry): Read the nullified class
+       init trampoline from the AOT file as well.
+
+       * mini-amd64.c (mono_arch_register_lowlevel_calls): Register
+       mono_amd64_throw_exception as a jit icall since it is needed by the aot-only
+       code.
+
+       * mini.c (mini_init): Move the call to mono_exceptions_init () after 
+       mono_init.
+
+       * exceptions-amd64.c: Add _full variants for the remaining exception code
+       creation functions as well, allow emission of relocatable code, remove
+       caching since that is now done by the caller.
+
+       * mini-exceptions.c: Add _full variants for the remaining exception code
+       creation functions as well, add aot-only support.
+
+       * aot-compiler.c (compile_method): Allow calls to methods of constructed types
+       if we can determine a proper token for them.
+       (add_wrappers): Add a few more wrappers.
+       (emit_method_code): Remove some dead code.
+       (emit_trampolines): Emit exception code too.
+
        * mini.c (mono_method_to_ir): Call mono_array_new_2 if possible.
 
        * jit-icalls.c (mono_array_new_2): New jit icall, specialized version of
index 81a3d987253ab6f1e07e0358ec38c30ff5a21297..bc9eaee4390ebfe15a92010a61516f72290b9643 100644 (file)
@@ -1718,6 +1718,19 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                g_assert (image_index < 255);
                token = ji->token;
 
+               /* Marker */
+               encode_value ((255 << 24), buf, &buf);
+               encode_value (image_index, buf, &buf);
+               encode_value (token, buf, &buf);
+       } else if (token == 0) {
+               /* This might be a method of a constructed type like int[,].Set */
+               /* Obtain the token from information recorded by the JIT */
+               ji = g_hash_table_lookup (acfg->token_info_hash, method);
+               g_assert (ji);
+               image_index = get_image_index (acfg, ji->image);
+               g_assert (image_index < 255);
+               token = ji->token;
+
                /* Marker */
                encode_value ((255 << 24), buf, &buf);
                encode_value (image_index, buf, &buf);
@@ -1906,21 +1919,28 @@ add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
 }
 
 static MonoMethod*
-get_runtime_invoke (const char *signature)
+get_runtime_invoke_sig (MonoMethodSignature *sig)
 {
        MonoMethodBuilder *mb;
        MonoMethod *m;
 
        mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
-       m = mono_mb_create_method (mb, mono_create_icall_signature (signature), 16);
+       m = mono_mb_create_method (mb, sig, 16);
        return mono_marshal_get_runtime_invoke (m);
 }
 
+static MonoMethod*
+get_runtime_invoke (const char *signature)
+{
+       return get_runtime_invoke_sig (mono_create_icall_signature (signature));
+}
+
 static void
 add_wrappers (MonoAotCompile *acfg)
 {
        MonoMethod *m;
        int i, nallocators;
+       MonoMethodSignature *csig;
 
        /* 
         * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
@@ -1938,6 +1958,29 @@ add_wrappers (MonoAotCompile *acfg)
        /* void runtime-invoke (string) [exception ctor] */
        add_method (acfg, get_runtime_invoke ("void string"));
 
+       /* void runtime-invoke (string, string) [exception ctor] */
+       add_method (acfg, get_runtime_invoke ("void string string"));
+
+       /* string runtime-invoke () [Exception.ToString ()] */
+       add_method (acfg, get_runtime_invoke ("string"));
+
+       /* void runtime-invoke (string, Exception) [exception ctor] */
+       csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+       csig->hasthis = 1;
+       csig->ret = &mono_defaults.void_class->byval_arg;
+       csig->params [0] = &mono_defaults.string_class->byval_arg;
+       csig->params [1] = &mono_defaults.exception_class->byval_arg;
+       add_method (acfg, get_runtime_invoke_sig (csig));
+
+       /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
+       csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+       csig->hasthis = 1;
+       csig->ret = &(mono_class_from_name (
+                                                                               mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
+       csig->params [0] = &mono_defaults.string_class->byval_arg;
+       csig->params [1] = &mono_defaults.boolean_class->byval_arg;
+       add_method (acfg, get_runtime_invoke_sig (csig));
+
        for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
                MonoMethod *method;
                guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
@@ -2142,118 +2185,6 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
        emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
 
-#if 0
-       /* Collect and sort relocations */
-       patches = g_ptr_array_new ();
-       for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
-               g_ptr_array_add (patches, patch_info);
-       g_ptr_array_sort (patches, compare_patches);
-
-       start_index = 0;
-       for (i = 0; i < cfg->code_len; i++) {
-               patch_info = NULL;
-               for (pindex = start_index; pindex < patches->len; ++pindex) {
-                       patch_info = g_ptr_array_index (patches, pindex);
-                       if (patch_info->ip.i >= i)
-                               break;
-               }
-
-#ifdef MONO_ARCH_AOT_SUPPORTED
-               skip = FALSE;
-               if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
-                       start_index = pindex;
-
-                       switch (patch_info->type) {
-                       case MONO_PATCH_INFO_NONE:
-                               break;
-                       case MONO_PATCH_INFO_GOT_OFFSET: {
-                               guint32 offset = mono_arch_get_patch_offset (code + i);
-                               emit_bytes (acfg, code + i, offset);
-                               emit_symbol_diff (acfg, "got", ".", offset);
-
-                               i += offset + 4 - 1;
-                               skip = TRUE;
-                               break;
-                       }
-                       default: {
-                               int plt_index;
-                               char *direct_call_target;
-
-                               if (!is_got_patch (patch_info->type))
-                                       break;
-
-                               /*
-                                * If this patch is a call, try emitting a direct call instead of
-                                * through a PLT entry. This is possible if the called method is in
-                                * the same assembly and requires no initialization.
-                                */
-                               direct_call_target = NULL;
-                               if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == cfg->method->klass->image)) {
-                                       MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
-                                       if (callee_cfg) {
-                                               if (!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)) {
-                                                       //printf ("DIRECT: %s %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (callee_cfg->method, TRUE));
-                                                       direct_call_target = g_strdup_printf (".Lm_%x", get_method_index (acfg, callee_cfg->method));
-                                                       patch_info->type = MONO_PATCH_INFO_NONE;
-                                                       acfg->stats.direct_calls ++;
-                                               }
-                                       }
-
-                                       acfg->stats.all_calls ++;
-                               }
-
-                               if (!direct_call_target) {
-                                       plt_index = get_plt_index (acfg, patch_info);
-                                       if (plt_index != -1) {
-                                               /* This patch has a PLT entry, so we must emit a call to the PLT entry */
-                                               direct_call_target = g_strdup_printf (".Lp_%d", plt_index);
-                                       }
-                               }
-
-                               if (direct_call_target) {
-#if defined(__i386__) || defined(__x86_64__)
-                                       g_assert (code [i] == 0xe8);
-                                       /* Need to make sure this is exactly 5 bytes long */
-                                       emit_byte (acfg, '\xe8');
-                                       emit_symbol_diff (acfg, direct_call_target, ".", -4);
-                                       i += 4;
-#elif defined(__arm__)
-#ifdef USE_BIN_WRITER
-                                       /* FIXME: Can't encode this using the current symbol writer functions */
-                                       g_assert_not_reached ();
-#else
-                                       emit_unset_mode (acfg);
-                                       fprintf (acfg->fp, "bl %s\n", direct_call_target);
-                                       i += 4 - 1;
-#endif
-#endif
-                               } else {
-                                       got_slot = get_got_offset (acfg, patch_info);
-
-                                       emit_bytes (acfg, code + i, mono_arch_get_patch_offset (code + i));
-#ifdef __x86_64__
-                                       emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
-#elif defined(__i386__)
-                                       emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
-#elif defined(__arm__)
-                                       emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
-#else
-                                       g_assert_not_reached ();
-#endif
-                                       
-                                       i += mono_arch_get_patch_offset (code + i) + 4 - 1;
-                               }
-                               skip = TRUE;
-                       }
-                       }
-               }
-#endif /* MONO_ARCH_AOT_SUPPORTED */
-
-               if (!skip)
-                       emit_bytes (acfg, code + i, 1);
-       }
-#endif
-
        emit_line (acfg);
 }
 
@@ -2900,8 +2831,8 @@ emit_plt (MonoAotCompile *acfg)
 }
 
 static void
-emit_named_code (MonoAotCompile *acfg, char *name, guint8 *code, guint32 code_size,
-                                int got_offset, MonoJumpInfo *ji)
+emit_named_code (MonoAotCompile *acfg, const char *name, guint8 *code, 
+                                guint32 code_size, int got_offset, MonoJumpInfo *ji)
 {
        char *symbol;
        guint32 buf_size;
@@ -2932,7 +2863,7 @@ emit_named_code (MonoAotCompile *acfg, char *name, guint8 *code, guint32 code_si
                g_ptr_array_add (patches, patch_info);
        g_ptr_array_sort (patches, compare_patches);
 
-       buf_size = patches->len * 128;
+       buf_size = patches->len * 128 + 128;
        buf = g_malloc (buf_size);
        p = buf;
 
@@ -2965,6 +2896,11 @@ emit_trampolines (MonoAotCompile *acfg)
 {
        char *symbol;
        int tramp_type, i, offset;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+       guint32 code_size;
+       MonoJumpInfo *ji;
+       guint8 *code;
+#endif
 
        if (!acfg->aot_opts.full_aot)
                return;
@@ -2982,10 +2918,6 @@ emit_trampolines (MonoAotCompile *acfg)
         * method.
         */
        for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
-               guint32 code_size;
-               MonoJumpInfo *ji;
-               guint8 *code;
-
                code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, TRUE);
 
                /* Emit trampoline code */
@@ -2996,6 +2928,23 @@ emit_trampolines (MonoAotCompile *acfg)
 
                g_free (symbol);
        }
+
+       code = mono_arch_get_nullified_class_init_trampoline (&code_size);
+       emit_named_code (acfg, "nullified_class_init_trampoline", code, code_size, acfg->got_offset, NULL);
+
+       /* Emit the exception related code pieces */
+       code = mono_arch_get_restore_context_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "restore_context", code, code_size, acfg->got_offset, ji);
+    code = mono_arch_get_call_filter_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "call_filter", code, code_size, acfg->got_offset, ji);
+       code = mono_arch_get_throw_exception_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "throw_exception", code, code_size, acfg->got_offset, ji);
+       code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji);
+       code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji);
+       code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
+       emit_named_code (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji);
 #endif
 
        /*
@@ -3253,14 +3202,11 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                skip = TRUE;
                                break;
                        }
-                       if (!patch_info->data.method->token)
-                               /*
-                                * The method is part of a constructed type like Int[,].Set (). It doesn't
-                                * have a token, and we can't make one, since the parent type is part of
-                                * assembly which contains the element type, and not the assembly which
-                                * referenced this type.
-                                */
-                               skip = TRUE;
+                       if (!patch_info->data.method->token) {
+                               /* The method is part of a constructed type like Int[,].Set (). */
+                               if (!g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
+                                       skip = TRUE;
+                       }
                        if (patch_info->data.method->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
                                /* FIXME: Can't encode these */
                                skip = TRUE;
index c63c9fd59fece61a05b45c4b136ae7025290ac16..451b2e40c92c113fb0e3419c52fb50bedee4f0c4 100644 (file)
@@ -77,6 +77,7 @@ typedef struct MonoAotModule {
        GHashTable *wrappers;
        MonoAssemblyName *image_names;
        char **image_guids;
+       MonoAssembly *assembly;
        MonoImage **image_table;
        guint32 image_table_len;
        gboolean out_of_date;
@@ -557,8 +558,10 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        }
 
        if (!usable) {
-               if (mono_aot_only)
-                       g_error ("Failed to load AOT module '%s' while running with --aot-only.\n", aot_name);
+               if (mono_aot_only) {
+                       fprintf (stderr, "Failed to load AOT module '%s' while running with --aot-only.\n", aot_name);
+                       exit (1);
+               }
                g_free (aot_name);
                mono_dl_close (assembly->aot_module);
                assembly->aot_module = NULL;
@@ -574,6 +577,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        info = g_new0 (MonoAotModule, 1);
        info->aot_name = aot_name;
+       info->assembly = assembly;
        info->got = got;
        info->got_size = *got_size_ptr;
        info->got [0] = assembly->image;
@@ -1292,6 +1296,8 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                ji->data.image = load_image (aot_module, decode_value (p, &p));
                if (!ji->data.image)
                        goto cleanup;
+               if (ji->data.image == aot_module->assembly->image)
+                       *got_offset = 0;
                break;
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -2140,16 +2146,31 @@ mono_aot_get_plt_entry (guint8 *code)
 }
 
 /*
- * Return the piece of code identified by NAME from the AOT file.
+ * Return the piece of code identified by NAME from the mscorlib AOT file.
  */
-static gpointer
-mono_aot_get_named_code (MonoAssembly *assembly, MonoAotModule *aot_module, char *name)
+gpointer
+mono_aot_get_named_code (const char *name)
 {
        char *symbol;
        guint8 *p;
        int n_patches, got_index, pindex;
        MonoMemPool *mp;
        gpointer code;
+       MonoImage *image;
+       MonoAssembly *assembly;
+       MonoAotModule *amodule;
+
+       image = mono_defaults.corlib;
+       g_assert (image);
+
+       mono_aot_lock ();
+
+       assembly = image->assembly;
+       g_assert (assembly);
+       amodule = (MonoAotModule*) g_hash_table_lookup (aot_modules, assembly);
+       g_assert (amodule);
+
+       mono_aot_unlock ();
 
        /* Load the code */
 
@@ -2177,33 +2198,46 @@ mono_aot_get_named_code (MonoAssembly *assembly, MonoAotModule *aot_module, char
 
                got_index = decode_value (p, &p);
 
-               patches = load_patch_info (aot_module, mp, n_patches, got_index, &got_slots, p, &p);
+               patches = load_patch_info (amodule, mp, n_patches, got_index, &got_slots, p, &p);
                g_assert (patches);
 
                for (pindex = 0; pindex < n_patches; ++pindex) {
                        MonoJumpInfo *ji = &patches [pindex];
                        gpointer target;
 
-                       g_assert (ji->type == MONO_PATCH_INFO_JIT_ICALL_ADDR);
-
                        /*
                         * When this code is executed, the runtime may not yet initalized, so
                         * resolve the patch info by hand.
                         */
-                       if (!strcmp (ji->data.name, "mono_get_lmf_addr")) {
-                               target = mono_get_lmf_addr;
-                       } else if (!strcmp (ji->data.name, "mono_thread_force_interruption_checkpoint")) {
-                               target = mono_thread_force_interruption_checkpoint;
-                       } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
-                               int tramp_type2 = atoi (ji->data.name + strlen ("trampoline_func_"));
-                               target = (gpointer)mono_get_trampoline_func (tramp_type2);
+                       if (ji->type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+                               if (!strcmp (ji->data.name, "mono_get_lmf_addr")) {
+                                       target = mono_get_lmf_addr;
+                               } else if (!strcmp (ji->data.name, "mono_thread_force_interruption_checkpoint")) {
+                                       target = mono_thread_force_interruption_checkpoint;
+                               } else if (!strcmp (ji->data.name, "mono_exception_from_token")) {
+                                       target = mono_exception_from_token;
+                               } else if (!strcmp (ji->data.name, "mono_throw_exception")) {
+                                       target = mono_get_throw_exception ();
+#ifdef __x86_64__
+                               } else if (!strcmp (ji->data.name, "mono_amd64_throw_exception")) {
+                                       target = mono_amd64_throw_exception;
+#endif
+                               } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
+                                       int tramp_type2 = atoi (ji->data.name + strlen ("trampoline_func_"));
+                                       target = (gpointer)mono_get_trampoline_func (tramp_type2);
+                               } else {
+                                       fprintf (stderr, "%s\n", ji->data.name);
+                                       g_assert_not_reached ();
+                                       target = NULL;
+                               }
                        } else {
-                               fprintf (stderr, "%s\n", ji->data.name);
-                               g_assert_not_reached ();
-                               target = NULL;
+                               /* Hopefully the code doesn't have patches which need method or 
+                                * domain to be set.
+                                */
+                               target = mono_resolve_patch_target (NULL, NULL, code, ji, FALSE);
                        }
 
-                       aot_module->got [got_slots [pindex]] = target;
+                       amodule->got [got_slots [pindex]] = target;
                }
 
                g_free (got_slots);
@@ -2246,7 +2280,7 @@ mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampo
                char *symbol;
 
                symbol = g_strdup_printf ("generic_trampoline_%d", tramp_type);
-               generic_trampolines [tramp_type] = mono_aot_get_named_code (image->assembly, amodule, symbol);
+               generic_trampolines [tramp_type] = mono_aot_get_named_code (symbol);
                g_free (symbol);
        }
 
@@ -2258,6 +2292,8 @@ mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampo
 
 #ifdef __x86_64__
        code = amodule->trampolines + (index * 16);
+       if (code_len)
+               *code_len = 16;
 #else
        g_assert_not_reached ();
 #endif
@@ -2365,4 +2401,10 @@ gpointer mono_aot_create_specific_trampolines (gpointer arg1, MonoTrampolineType
        g_assert_not_reached ();
 }
 
+gpointer
+mono_aot_get_named_code (char *name)
+{
+       g_assert_not_reached ();
+}
+
 #endif
index a9892070d599d0b3d51e8cc737c6f62c36b799b8..18ad406750dc228cc030f7e7d0c3b9bc64003105 100644 (file)
@@ -145,13 +145,9 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
 gpointer
 mono_arch_get_restore_context_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
-       static guint8 *start = NULL;
-       static gboolean inited = FALSE;
+       guint8 *start = NULL;
        guint8 *code;
 
-       if (inited)
-               return start;
-
        /* restore_contect (MonoContext *ctx) */
 
        *ji = NULL;
@@ -188,8 +184,6 @@ mono_arch_get_restore_context_full (guint32 *code_size, MonoJumpInfo **ji, gbool
 
        *code_size = code - start;
 
-       inited = TRUE;
-
        return start;
 }
 
@@ -203,15 +197,11 @@ mono_arch_get_restore_context_full (guint32 *code_size, MonoJumpInfo **ji, gbool
 gpointer
 mono_arch_get_call_filter_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
-       static guint8 *start;
-       static gboolean inited = FALSE;
+       guint8 *start;
        int i;
        guint8 *code;
        guint32 pos;
 
-       if (inited)
-               return start;
-
        *ji = NULL;
 
        start = code = mono_global_codeman_reserve (128);
@@ -275,8 +265,6 @@ mono_arch_get_call_filter_full (guint32 *code_size, MonoJumpInfo **ji, gboolean
 
        *code_size = code - start;
 
-       inited = TRUE;
-
        return start;
 }
 
@@ -284,14 +272,14 @@ mono_arch_get_call_filter_full (guint32 *code_size, MonoJumpInfo **ji, gboolean
  * The first few arguments are dummy, to force the other arguments to be passed on
  * the stack, this avoids overwriting the argument registers in the throw trampoline.
  */
-static void
-throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
-                                guint64 dummy5, guint64 dummy6,
-                                MonoObject *exc, guint64 rip, guint64 rsp,
-                                guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, 
-                                guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, 
-                                guint64 rax, guint64 rcx, guint64 rdx,
-                                guint64 rethrow)
+void
+mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
+                                                       guint64 dummy5, guint64 dummy6,
+                                                       MonoObject *exc, guint64 rip, guint64 rsp,
+                                                       guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, 
+                                                       guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, 
+                                                       guint64 rax, guint64 rcx, guint64 rdx,
+                                                       guint64 rethrow)
 {
        static void (*restore_context) (MonoContext *);
        MonoContext ctx;
@@ -351,7 +339,7 @@ throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
 }
 
 static gpointer
-get_throw_trampoline (gboolean rethrow)
+get_throw_trampoline (gboolean rethrow, guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
        guint8* start;
        guint8 *code;
@@ -360,6 +348,8 @@ get_throw_trampoline (gboolean rethrow)
 
        code = start;
 
+       *ji = NULL;
+
        amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, 8);
 
        /* reverse order */
@@ -396,7 +386,12 @@ get_throw_trampoline (gboolean rethrow)
        amd64_push_imm (code, 0);
 #endif
 
-       amd64_mov_reg_imm (code, AMD64_R11, throw_exception);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_throw_exception");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_R11, mono_amd64_throw_exception);
+       }
        amd64_call_reg (code, AMD64_R11);
        amd64_breakpoint (code);
 
@@ -404,6 +399,8 @@ get_throw_trampoline (gboolean rethrow)
 
        g_assert ((code - start) < 64);
 
+       *code_size = code - start;
+
        return start;
 }
 
@@ -418,52 +415,32 @@ get_throw_trampoline (gboolean rethrow)
 gpointer 
 mono_arch_get_throw_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
-       static guint8* start;
-       static gboolean inited = FALSE;
-
-       if (inited)
-               return start;
-
-       start = get_throw_trampoline (FALSE);
-
-       inited = TRUE;
-
-       return start;
+       return get_throw_trampoline (FALSE, code_size, ji, aot);
 }
 
 gpointer 
 mono_arch_get_rethrow_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
-       static guint8* start;
-       static gboolean inited = FALSE;
-
-       if (inited)
-               return start;
-
-       start = get_throw_trampoline (TRUE);
-
-       inited = TRUE;
-
-       return start;
+       return get_throw_trampoline (TRUE, code_size, ji, aot);
 }
 
 gpointer 
-mono_arch_get_throw_exception_by_name (void)
+mono_arch_get_throw_exception_by_name_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {      
-       static guint8* start;
-       static gboolean inited = FALSE;
+       guint8* start;
        guint8 *code;
 
-       if (inited)
-               return start;
-
        start = code = mono_global_codeman_reserve (64);
 
+       *ji = NULL;
+
        /* Not used on amd64 */
        amd64_breakpoint (code);
 
        mono_arch_flush_icache (start, code - start);
 
+       *code_size = code - start;
+
        return start;
 }
 
@@ -478,25 +455,30 @@ mono_arch_get_throw_exception_by_name (void)
  * needs no relocations in the caller.
  */
 gpointer 
-mono_arch_get_throw_corlib_exception (void)
+mono_arch_get_throw_corlib_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
        static guint8* start;
-       static gboolean inited = FALSE;
        guint8 *code;
        guint64 throw_ex;
 
-       if (inited)
-               return start;
-
        start = code = mono_global_codeman_reserve (64);
 
+       *ji = NULL;
+
        /* Push throw_ip */
        amd64_push_reg (code, AMD64_ARG_REG2);
 
        /* Call exception_from_token */
        amd64_mov_reg_reg (code, AMD64_ARG_REG2, AMD64_ARG_REG1, 8);
-       amd64_mov_reg_imm (code, AMD64_ARG_REG1, mono_defaults.exception_class->image);
-       amd64_mov_reg_imm (code, AMD64_R11, mono_exception_from_token);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_IMAGE, mono_defaults.exception_class->image);
+               amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RIP, 0, 8);
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_exception_from_token");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_ARG_REG1, mono_defaults.exception_class->image);
+               amd64_mov_reg_imm (code, AMD64_R11, mono_exception_from_token);
+       }
        amd64_call_reg (code, AMD64_R11);
 
        /* Compute throw_ip */
@@ -512,7 +494,12 @@ mono_arch_get_throw_corlib_exception (void)
 
        /* Call throw_exception */
        amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, 8);
-       amd64_mov_reg_imm (code, AMD64_R11, throw_ex);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_throw_exception");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_R11, throw_ex);
+       }
        /* The original IP is on the stack */
        amd64_jump_reg (code, AMD64_R11);
 
@@ -520,7 +507,7 @@ mono_arch_get_throw_corlib_exception (void)
 
        mono_arch_flush_icache (start, code - start);
 
-       inited = TRUE;
+       *code_size = code - start;
 
        return start;
 }
index 64860ebdd5b127841819ddbbcdedb5d5e94a418d..54492b28029da74931f34592f8853dc0ab820b3c 100644 (file)
@@ -3892,6 +3892,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 void
 mono_arch_register_lowlevel_calls (void)
 {
+       /* The signature doesn't matter */
+       mono_register_jit_icall (mono_amd64_throw_exception, "mono_amd64_throw_exception", mono_create_icall_signature ("void"), TRUE);
 }
 
 void
index 133ef98135d7f460fec1b631d3eab7b6ce870406..7cada8a7e10c171d68a2e147aadcfb639b7bd323 100644 (file)
@@ -59,10 +59,17 @@ mono_exceptions_init (void)
        guint32 code_size;
        MonoJumpInfo *ji;
 
-       restore_context_func = mono_arch_get_restore_context_full (&code_size, &ji, FALSE);
-       call_filter_func = mono_arch_get_call_filter_full (&code_size, &ji, FALSE);
-       throw_exception_func = mono_arch_get_throw_exception_full (&code_size, &ji, FALSE);
-       rethrow_exception_func = mono_arch_get_rethrow_exception_full (&code_size, &ji, FALSE);
+       if (mono_aot_only) {
+               restore_context_func = mono_aot_get_named_code ("restore_context");
+               call_filter_func = mono_aot_get_named_code ("call_filter");
+               throw_exception_func = mono_aot_get_named_code ("throw_exception");
+               rethrow_exception_func = mono_aot_get_named_code ("rethrow_exception");
+       } else {
+               restore_context_func = mono_arch_get_restore_context_full (&code_size, &ji, FALSE);
+               call_filter_func = mono_arch_get_call_filter_full (&code_size, &ji, FALSE);
+               throw_exception_func = mono_arch_get_throw_exception_full (&code_size, &ji, FALSE);
+               rethrow_exception_func = mono_arch_get_rethrow_exception_full (&code_size, &ji, FALSE);
+       }
 #else
 #ifndef CUSTOM_EXCEPTION_HANDLING
        restore_context_func = mono_arch_get_restore_context ();
@@ -105,12 +112,23 @@ gpointer
 mono_get_throw_exception_by_name (void)
 {
        gpointer code = NULL;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+       guint32 code_size;
+       MonoJumpInfo *ji;
+#endif
 
        /* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
        if (throw_exception_by_name_func)
                return throw_exception_by_name_func;
 
-       code = mono_arch_get_throw_exception_by_name ();
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+       if (mono_aot_only)
+               code = mono_aot_get_named_code ("throw_exception_by_name");
+       else
+               code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, FALSE);
+#else
+               code = mono_arch_get_throw_exception_by_name ();
+#endif
 
        mono_memory_barrier ();
 
@@ -123,13 +141,24 @@ gpointer
 mono_get_throw_corlib_exception (void)
 {
        gpointer code = NULL;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+       guint32 code_size;
+       MonoJumpInfo *ji;
+#endif
 
        /* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
        if (throw_corlib_exception_func)
                return throw_corlib_exception_func;
 
 #if MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION
-       code = mono_arch_get_throw_corlib_exception ();
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+       if (mono_aot_only)
+               code = mono_aot_get_named_code ("throw_corlib_exception");
+       else
+               code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, FALSE);
+#else
+               code = mono_arch_get_throw_corlib_exception ();
+#endif
 #else
        g_assert_not_reached ();
 #endif
index d2095181238e80b598f25aca35fac92c98f03341..0975d1b125c67e448d72f6bdab1ba87a0bbec60f 100644 (file)
@@ -13868,8 +13868,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_trampolines_init ();
 
-       mono_exceptions_init ();
-
        if (!g_thread_supported ())
                g_thread_init (NULL);
 
@@ -13911,7 +13909,6 @@ mini_init (const char *filename, const char *runtime_version)
 #define JIT_INVOKE_WORKS
 #ifdef JIT_INVOKE_WORKS
        mono_install_runtime_invoke (mono_jit_runtime_invoke);
-       mono_install_handler (mono_get_throw_exception ());
 #endif
        mono_install_stack_walk (mono_jit_walk_stack);
        mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
@@ -13934,6 +13931,11 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_vtable_trampoline (mini_get_vtable_trampoline ());
 #endif
 #endif
+
+       /* This must come after mono_init () in the aot-only case */
+       mono_exceptions_init ();
+       mono_install_handler (mono_get_throw_exception ());
+
        mono_icall_init ();
 
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
index 5dd32298a14e76544a3b2014299dd7a1b9dccca4..85531569541a13c5432df738a53635027195ed08 100644 (file)
@@ -1112,6 +1112,7 @@ MonoJitICallInfo *mono_find_jit_opcode_emulation (int opcode) MONO_INTERNAL;
 void     mono_print_ins_index (int i, MonoInst *ins) MONO_INTERNAL;
 void     mono_print_ins (MonoInst *ins) MONO_INTERNAL;
 
+/* AOT */
 void      mono_aot_init                     (void) MONO_INTERNAL;
 gpointer  mono_aot_get_method               (MonoDomain *domain,
                                                                                         MonoMethod *method) MONO_INTERNAL;
@@ -1128,6 +1129,7 @@ guint32 mono_aot_get_n_pagefaults           (void) MONO_INTERNAL;
 gpointer mono_aot_plt_resolve               (gpointer aot_module, guint32 plt_info_offset, guint8 *code) MONO_INTERNAL;
 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_named_code (const char *name) MONO_INTERNAL;
 
 gboolean  mono_method_blittable             (MonoMethod *method) MONO_INTERNAL;
 gboolean  mono_method_same_domain           (MonoJitInfo *caller, MonoJitInfo *callee) MONO_INTERNAL;
@@ -1205,6 +1207,7 @@ guchar*   mono_arch_create_trampoline_code      (MonoTrampolineType tramp_type)
 guchar*   mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 gpointer  mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
 guint32          mono_arch_get_rgctx_lazy_fetch_offset (gpointer *regs) MONO_INTERNAL;
+gpointer  mono_arch_get_nullified_class_init_trampoline (guint32 *code_len) MONO_INTERNAL;
 GList    *mono_arch_get_allocatable_int_vars    (MonoCompile *cfg) MONO_INTERNAL;
 GList    *mono_arch_get_global_int_regs         (MonoCompile *cfg) MONO_INTERNAL;
 guint32   mono_arch_regalloc_cost               (MonoCompile *cfg, MonoMethodVar *vmv) MONO_INTERNAL;
@@ -1241,6 +1244,8 @@ gpointer mono_arch_get_call_filter_full         (guint32 *code_size, MonoJumpInf
 gpointer mono_arch_get_restore_context_full     (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 gpointer  mono_arch_get_throw_exception_full    (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 gpointer  mono_arch_get_rethrow_exception_full  (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer  mono_arch_get_throw_exception_by_name_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer  mono_arch_get_throw_corlib_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 gboolean mono_arch_handle_exception             (void *sigctx, gpointer obj, gboolean test_only) MONO_INTERNAL;
 void     mono_arch_handle_altstack_exception    (void *sigctx, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
 gpointer mono_arch_ip_from_context              (void *sigctx) MONO_INTERNAL;
index 87e4e8ac02ffd0e12ccc982087069ec39afc57d9..6b4e2339d483445632fc2d24f9ff9b4a7276cc66 100644 (file)
@@ -203,6 +203,9 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
 void
 mono_arch_nullify_plt_entry (guint8 *code)
 {
+       if (mono_aot_only && !nullified_class_init_trampoline)
+               nullified_class_init_trampoline = mono_aot_get_named_code ("nullified_class_init_trampoline");
+
        mono_arch_patch_plt_entry (code, nullified_class_init_trampoline);
 }
 
@@ -475,6 +478,14 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c
                if (AMD64_IS_ARGUMENT_REG (i) || i == AMD64_R10 || i == AMD64_R11)
                        amd64_mov_reg_membase (code, i, AMD64_RBP, saved_regs_offset + (i * 8), 8);
 
+       /* 
+        * FIXME: When using aot-only, the called code might be a C vararg function 
+        * which uses %rax as well.
+        * We could restore it, but we would have to use another register to store the
+        * target address, and we don't have any left.
+        * Also, the default AOT plt trampolines overwrite 'rax'.
+        */
+
        for (i = 0; i < 8; ++i)
                amd64_movsd_reg_membase (code, i, AMD64_RBP, saved_fpregs_offset + (i * 8));
 
@@ -485,21 +496,38 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c
                        tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT ||
                        tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
                amd64_ret (code);
-       else
+       else {
                /* call the compiled method */
-               amd64_jump_reg (code, X86_EAX);
+               amd64_jump_reg (code, AMD64_RAX);
+       }
 
        g_assert ((code - buf) <= 524);
 
        mono_arch_flush_icache (buf, code - buf);
 
+       *code_size = code - buf;
+
        if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
+               guint32 code_len;
+
                /* Initialize the nullified class init trampoline used in the AOT case */
-               nullified_class_init_trampoline = code = mono_global_codeman_reserve (16);
-               x86_ret (code);
+               nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len);
        }
 
-       *code_size = code - buf;
+       return buf;
+}
+
+gpointer
+mono_arch_get_nullified_class_init_trampoline (guint32 *code_len)
+{
+       guint8 *code, *buf;
+
+       code = buf = mono_global_codeman_reserve (16);
+       amd64_ret (code);
+
+       mono_arch_flush_icache (buf, code - buf);
+
+       *code_len = code - buf;
 
        return buf;
 }