2009-02-09 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Mon, 9 Feb 2009 15:33:25 +0000 (15:33 -0000)
committerZoltan Varga <vargaz@gmail.com>
Mon, 9 Feb 2009 15:33:25 +0000 (15:33 -0000)
* aot-compiler.c (emit_trampolines): Add throw_pending_exception/
generic_class_init trampolines.
(add_generic_class): Extract some code from add_generic_instances () into a
separate function so it can be called from other places too.
(compile_method): Call add_generic_class () for the classes of inflated methods
referenced by the method.
(can_encode_patch): Allow references to generic parameters.

* aot-runtime.c: Add support the patches required by the new trampolines.

* exceptions-amd64.c (mono_arch_get_throw_pending_exception_full): Add full-aot
support.

* tramp-amd64.c (mono_arch_create_generic_class_init_trampoline_full): Add
full-aot support.

* exceptions-amd64.c (mono_arch_get_throw_pending_exception_full): Rename
this from get_throw_pending_exception, make the signature full aot compatible.

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

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

index bceaf36f5e900efd44dfc672fd7d3a6667c5f62c..b1a6e7c79f47938b05f4db7e72c605b08e8437fe 100644 (file)
@@ -1,5 +1,21 @@
 2009-02-09  Zoltan Varga  <vargaz@gmail.com>
 
+       * aot-compiler.c (emit_trampolines): Add throw_pending_exception/
+       generic_class_init trampolines.
+       (add_generic_class): Extract some code from add_generic_instances () into a
+       separate function so it can be called from other places too.
+       (compile_method): Call add_generic_class () for the classes of inflated methods
+       referenced by the method.
+       (can_encode_patch): Allow references to generic parameters.
+
+       * aot-runtime.c: Add support the patches required by the new trampolines.
+       
+       * exceptions-amd64.c (mono_arch_get_throw_pending_exception_full): Add full-aot
+       support.
+
+       * tramp-amd64.c (mono_arch_create_generic_class_init_trampoline_full): Add
+       full-aot support.
+
        * exceptions-amd64.c (mono_arch_get_throw_pending_exception_full): Rename
        this from get_throw_pending_exception, make the signature full aot compatible.
 
index ced48e863e0df819e81d0c164fec4c44f4ce87d4..cb607de8edf410593cb1a195c9431d91ffb76996 100644 (file)
@@ -2373,7 +2373,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
                        else
                                g_assert_not_reached ();
                        break;
-               case MONO_WRAPPER_STATIC_RGCTX_INVOKE: {
+               case MONO_WRAPPER_STATIC_RGCTX_INVOKE:
+               case MONO_WRAPPER_SYNCHRONIZED: {
                        MonoMethod *m;
 
                        m = mono_marshal_method_from_wrapper (method);
@@ -2927,6 +2928,55 @@ method_has_type_vars (MonoMethod *method)
        return FALSE;
 }
 
+/*
+ * add_generic_class:
+ *
+ *   Add all methods of a generic class.
+ */
+static void
+add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
+{
+       MonoMethod *method;
+       gpointer iter;
+
+       mono_class_init (klass);
+
+       if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
+               return;
+
+       if (has_type_vars (klass))
+               return;
+
+       if (!klass->generic_class && !klass->rank)
+               return;
+
+       /* 
+        * Add rgctx wrappers for cctors since those are called by the runtime, so 
+        * there is no methodspec for them. This is needed even for shared classes,
+        * since rgctx wrappers belong to inflated methods.
+        */
+       method = mono_class_get_cctor (klass);
+       if (method)
+               add_extra_method (acfg, mono_marshal_get_static_rgctx_invoke (method));
+
+       iter = NULL;
+       while ((method = mono_class_get_methods (klass, &iter))) {
+               if (mono_method_is_generic_sharable_impl (method, FALSE))
+                       /* Already added */
+                       continue;
+
+               if (method->is_generic)
+                       /* FIXME: */
+                       continue;
+
+               /*
+                * FIXME: Instances which are referenced by these methods are not added,
+                * for example Array.Resize<int> for List<int>.Add ().
+                */
+               add_extra_method (acfg, method);
+       }
+}
+
 /*
  * add_generic_instances:
  *
@@ -2961,49 +3011,14 @@ add_generic_instances (MonoAotCompile *acfg)
 
        for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
                MonoClass *klass;
-               gpointer iter;
 
                token = MONO_TOKEN_TYPE_SPEC | (i + 1);
 
                klass = mono_class_get (acfg->image, token);
                if (!klass)
                        continue;
-               mono_class_init (klass);
-
-               if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
-                       continue;
-
-               if (has_type_vars (klass))
-                       continue;
-
-               if (!klass->generic_class && !klass->rank)
-                       continue;
-
-               /* 
-                * Add rgctx wrappers for cctors since those are called by the runtime, so 
-                * there is no methodspec for them. This is needed even for shared classes,
-                * since rgctx wrappers belong to inflated methods.
-                */
-               method = mono_class_get_cctor (klass);
-               if (method)
-                       add_extra_method (acfg, mono_marshal_get_static_rgctx_invoke (method));
 
-               iter = NULL;
-               while ((method = mono_class_get_methods (klass, &iter))) {
-                       if (mono_method_is_generic_sharable_impl (method, FALSE))
-                               /* Already added */
-                               continue;
-
-                       if (method->is_generic)
-                               /* FIXME: */
-                               continue;
-
-                       /*
-                        * FIXME: Instances which are referenced by these methods are not added,
-                        * for example Array.Resize<int> for List<int>.Add ().
-                        */
-                       add_extra_method (acfg, method);
-               }
+               add_generic_class (acfg, klass);
        }
 }
 
@@ -3870,6 +3885,11 @@ emit_trampolines (MonoAotCompile *acfg)
                emit_named_code (acfg, "monitor_exit_trampoline", code, code_size, acfg->got_offset, ji);
 #endif
 
+#if defined(__x86_64__)
+               code = mono_arch_create_generic_class_init_trampoline_full (&code_size, &ji, TRUE);
+               emit_named_code (acfg, "generic_class_init_trampoline", code, code_size, acfg->got_offset, ji);
+#endif
+
                /* 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);
@@ -3884,6 +3904,11 @@ emit_trampolines (MonoAotCompile *acfg)
                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);
 
+#if defined(__x86_64__)
+               code = mono_arch_get_throw_pending_exception_full (&code_size, &ji, TRUE);
+               emit_named_code (acfg, "throw_pending_exception", code, code_size, acfg->got_offset, ji);
+#endif
+
 #if defined(__x86_64__) || defined(__arm__)
                for (i = 0; i < 128; ++i) {
                        int offset;
@@ -4132,7 +4157,7 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                        case MONO_WRAPPER_UNKNOWN:
                                break;
                        default:
-                               //printf ("Skip (wrapper call):   %s %d -> %s\n", mono_method_full_name (method, TRUE), patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
+                               //printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
                                return FALSE;
                        }
                } else {
@@ -4148,11 +4173,16 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
-       case MONO_PATCH_INFO_ADJUSTED_IID:
-               if (!patch_info->data.klass->type_token)
-                       if (!patch_info->data.klass->element_class->type_token && !(patch_info->data.klass->element_class->rank && patch_info->data.klass->element_class->element_class->type_token))
+       case MONO_PATCH_INFO_ADJUSTED_IID: {
+               MonoClass *klass = patch_info->data.klass;
+
+               if (!klass->type_token)
+                       if (!klass->element_class->type_token && !(klass->element_class->rank && klass->element_class->element_class->type_token) && (klass->byval_arg.type != MONO_TYPE_VAR) && (klass->byval_arg.type != MONO_TYPE_MVAR)) {
+                               //printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
                                return FALSE;
+                       }
                break;
+       }
        case MONO_PATCH_INFO_RGCTX_FETCH: {
                MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
 
@@ -4167,6 +4197,9 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
        return TRUE;
 }
 
+static void
+add_generic_class (MonoAotCompile *acfg, MonoClass *klass);
+
 /*
  * compile_method:
  *
@@ -4299,6 +4332,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                return;
        }
 
+       //printf ("X: %s\n", mono_method_full_name (method, TRUE));
+
        /* Adds generic instances referenced by this method */
        for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
                switch (patch_info->type) {
@@ -4309,6 +4344,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                                          mono_method_is_generic_sharable_impl (m, FALSE)) &&
                                        !method_has_type_vars (m))
                                        add_extra_method (acfg, m);
+                               add_generic_class (acfg, m->klass);
                        }
                        break;
                }
@@ -6693,6 +6729,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
                method = mono_get_method (acfg->image, token, NULL);
 
+               if (!method) {
+                       printf ("Failed to load method 0x%x from '%s'.\n", token, image->name);
+                       exit (1);
+               }
+                       
                /* Load all methods eagerly to skip the slower lazy loading code */
                mono_class_setup_methods (method->klass);
 
index f7b10a53b3a93c70294a86de7e00341938ed0faf..7ceaadb0e1b87479dd785670ca8fbdf105c4e6d3 100644 (file)
@@ -50,6 +50,7 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/monitor.h>
+#include <mono/metadata/threads-types.h>
 #include <mono/utils/mono-logger.h>
 #include "mono/utils/mono-compiler.h"
 
@@ -2593,6 +2594,10 @@ load_named_code (MonoAotModule *amodule, const char *name)
                                } else if (!strcmp (ji->data.name, "mono_amd64_throw_exception")) {
                                        target = mono_amd64_throw_exception;
 #endif
+#ifdef __x86_64__
+                               } else if (!strcmp (ji->data.name, "mono_amd64_get_original_ip")) {
+                                       target = mono_amd64_get_original_ip;
+#endif
 #ifdef __arm__
                                } else if (!strcmp (ji->data.name, "mono_arm_throw_exception")) {
                                        target = mono_arm_throw_exception;
@@ -2612,6 +2617,10 @@ load_named_code (MonoAotModule *amodule, const char *name)
                                        target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
                                } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
                                        target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
+                               } else if (!strcmp (ji->data.name, "specific_trampoline_generic_class_init")) {
+                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL);
+                               } else if (!strcmp (ji->data.name, "mono_thread_get_and_clear_pending_exception")) {
+                                       target = mono_thread_get_and_clear_pending_exception;
                                } else {
                                        fprintf (stderr, "Unknown relocation '%s'\n", ji->data.name);
                                        g_assert_not_reached ();
index 30358ea413b51102f7fc9efd43252e97fdcfc5db..d368bea83e3a89522ea68f300928d045866be9f2 100644 (file)
@@ -882,8 +882,8 @@ mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean
 #endif
 }
 
-static guint64
-get_original_ip (void)
+guint64
+mono_amd64_get_original_ip (void)
 {
        MonoLMF *lmf = mono_get_lmf ();
 
@@ -904,8 +904,6 @@ mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **j
 
        *ji = NULL;
 
-       g_assert (!aot);
-
        start = code = mono_global_codeman_reserve (128);
 
        /* We are in the frame of a managed method after a call */
@@ -925,7 +923,12 @@ mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **j
        amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8);
 
        /* Obtain the pending exception */
-       amd64_mov_reg_imm (code, AMD64_R11, mono_thread_get_and_clear_pending_exception);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_thread_get_and_clear_pending_exception");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_R11, mono_thread_get_and_clear_pending_exception);
+       }
        amd64_call_reg (code, AMD64_R11);
 
        /* Check if it is NULL, and branch */
@@ -940,7 +943,12 @@ mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **j
        amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8);
 
        /* Obtain the original ip and clear the flag in previous_lmf */
-       amd64_mov_reg_imm (code, AMD64_R11, get_original_ip);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_get_original_ip");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_R11, mono_amd64_get_original_ip);
+       }
        amd64_call_reg (code, AMD64_R11);       
 
        /* Load exc */
@@ -956,8 +964,13 @@ mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **j
        amd64_push_reg (code, AMD64_RAX);
 
        /* Call the throw trampoline */
-       throw_trampoline = mono_get_throw_exception ();
-       amd64_mov_reg_imm (code, AMD64_R11, throw_trampoline);
+       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 {
+               throw_trampoline = mono_get_throw_exception ();
+               amd64_mov_reg_imm (code, AMD64_R11, throw_trampoline);
+       }
        /* We use a jump instead of a call so we can push the original ip on the stack */
        amd64_jump_reg (code, AMD64_R11);
 
@@ -965,7 +978,12 @@ mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **j
        mono_amd64_patch (br [0], code);
 
        /* Obtain the original ip and clear the flag in previous_lmf */
-       amd64_mov_reg_imm (code, AMD64_R11, get_original_ip);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_get_original_ip");
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+       } else {
+               amd64_mov_reg_imm (code, AMD64_R11, mono_amd64_get_original_ip);
+       }
        amd64_call_reg (code, AMD64_R11);       
        amd64_mov_reg_reg (code, AMD64_R11, AMD64_RAX, 8);
 
@@ -1021,8 +1039,12 @@ mono_arch_exceptions_init (void)
        guint32 code_size;
        MonoJumpInfo *ji;
 
-       /* Call this to avoid initialization races */
-       throw_pending_exception = mono_arch_get_throw_pending_exception_full (&code_size, &ji, FALSE);
+       if (mono_aot_only) {
+               throw_pending_exception = mono_aot_get_named_code ("throw_pending_exception");
+       } else {
+               /* Call this to avoid initialization races */
+               throw_pending_exception = mono_arch_get_throw_pending_exception_full (&code_size, &ji, FALSE);
+       }
 }
 
 #ifdef PLATFORM_WIN32
index 939109f9e0d24d1eeb9d98b5afda32e2a0071dc5..83a9f9ae12939e48f44418d9de19c7b1529cc465 100644 (file)
@@ -356,6 +356,9 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin
                                                        guint64 rax, guint64 rcx, guint64 rdx,
                                                        guint64 rethrow);
 
+guint64
+mono_amd64_get_original_ip (void) MONO_INTERNAL;
+
 guint8*
 mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset) MONO_INTERNAL;
 
index 199cae2bdb45e9d2b9275350fefc52243fffd589..24f1e8fe949c1123e985dec8313c8473502a9d82 100644 (file)
@@ -794,8 +794,12 @@ mono_create_generic_class_init_trampoline (void)
 
        mono_trampolines_lock ();
 
-       if (!code)
-               code = mono_arch_create_generic_class_init_trampoline ();
+       if (!code) {
+               if (mono_aot_only)
+                       code = mono_aot_get_named_code ("generic_class_init_trampoline");
+               else
+                       code = mono_arch_create_generic_class_init_trampoline ();
+       }
 
        mono_trampolines_unlock ();
 
index 083a3340bea412b2fe10fd04bba8ea60c5ce7f9e..9a9e04cc19c1f38ef6a36fcccaf3197a5600905f 100644 (file)
@@ -1398,6 +1398,7 @@ gpointer  mono_arch_create_monitor_enter_trampoline (void) MONO_INTERNAL;
 gpointer  mono_arch_create_monitor_exit_trampoline (void) MONO_INTERNAL;
 gpointer  mono_arch_create_monitor_enter_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 gpointer  mono_arch_create_monitor_exit_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer  mono_arch_create_generic_class_init_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
 GList    *mono_arch_get_allocatable_int_vars    (MonoCompile *cfg) MONO_INTERNAL;
 GList    *mono_arch_get_global_int_regs         (MonoCompile *cfg) MONO_INTERNAL;
 GList    *mono_arch_get_global_fp_regs          (MonoCompile *cfg) MONO_INTERNAL;
index 5559f52949876079df93605815a85a3bdb34cafc..5498cfc706f84281d56e0f0f888f192383bfbd6b 100644 (file)
@@ -670,6 +670,15 @@ mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_s
 
 gpointer
 mono_arch_create_generic_class_init_trampoline (void)
+{
+       guint32 code_size;
+       MonoJumpInfo *ji;
+
+       return mono_arch_create_generic_class_init_trampoline_full (&code_size, &ji, FALSE);
+}
+
+gpointer
+mono_arch_create_generic_class_init_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
 {
        guint8 *tramp;
        guint8 *code, *buf;
@@ -678,6 +687,8 @@ mono_arch_create_generic_class_init_trampoline (void)
        guint8 *jump;
        int tramp_size;
 
+       *ji = NULL;
+
        tramp_size = 64;
 
        code = buf = mono_global_codeman_reserve (tramp_size);
@@ -693,15 +704,23 @@ mono_arch_create_generic_class_init_trampoline (void)
 
        x86_patch (jump, code);
 
-       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL);
+       if (aot) {
+               *ji = mono_patch_info_list_prepend (*ji, buf - code, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_generic_class_init");
+               amd64_mov_reg_membase (buf, AMD64_R11, AMD64_RIP, 0, 8);
+               amd64_jump_reg (buf, AMD64_R11);
+       } else {
+               tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL);
 
-       /* jump to the actual trampoline */
-       amd64_jump_code (code, tramp);
+               /* jump to the actual trampoline */
+               amd64_jump_code (code, tramp);
+       }
 
        mono_arch_flush_icache (buf, code - buf);
 
        g_assert (code - buf <= tramp_size);
 
+       *code_size = code - buf;
+
        return buf;
 }