2005-07-07 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mono / mini / tramp-x86.c
index 15f40950d22e10aa8a51306ca752f5754c95f99d..454fa396778e68657218ee93f2e89fdfd6f04db2 100644 (file)
 #include "mini.h"
 #include "mini-x86.h"
 
-typedef enum {
-       MONO_TRAMPOLINE_GENERIC,
-       MONO_TRAMPOLINE_JUMP,
-       MONO_TRAMPOLINE_CLASS_INIT,
-       MONO_TRAMPOLINE_AOT
-} MonoTrampolineType;
-
-/* adapt to mini later... */
-#define mono_jit_share_code (1)
-
-/*
- * Address of the x86 trampoline code.  This is used by the debugger to check
- * whether a method is a trampoline.
- */
-guint8 *mono_generic_trampoline_code = NULL;
+static guint8* nullified_class_init_trampoline;
 
 /*
  * get_unbox_trampoline:
@@ -125,7 +111,7 @@ x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
                if ((code [1] == 0xe8)) {
                        if (!mono_running_on_valgrind ()) {
                                MonoJitInfo *ji = 
-                                       mono_jit_info_table_find (mono_domain_get (), code);
+                                       mono_jit_info_table_find (mono_domain_get (), (char*)code);
                                MonoJitInfo *target_ji = 
                                        mono_jit_info_table_find (mono_domain_get (), addr);
 
@@ -167,24 +153,29 @@ x86_aot_trampoline (int eax, int ecx, int edx, int esi, int edi,
 {
        MonoImage *image;
        guint32 token;
-       MonoMethod *method;
+       MonoMethod *method = NULL;
        gpointer addr;
        gpointer *vtable_slot;
        int regs [X86_NREG];
+       gboolean is_got_entry;
 
        image = *(gpointer*)token_info;
        token_info += sizeof (gpointer);
        token = *(guint32*)token_info;
 
-       /* Later we could avoid allocating the MonoMethod */
-       method = mono_get_method (image, token, NULL);
-       g_assert (method);
+       addr = mono_aot_get_method_from_token (mono_domain_get (), image, token);
+       if (!addr) {
+               method = mono_get_method (image, token, NULL);
+               g_assert (method);
 
-       if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
-               method = mono_marshal_get_synchronized_wrapper (method);
+               //printf ("F: %s\n", mono_method_full_name (method, TRUE));
 
-       addr = mono_compile_method (method);
-       g_assert (addr);
+               if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+                       method = mono_marshal_get_synchronized_wrapper (method);
+
+               addr = mono_compile_method (method);
+               g_assert (addr);
+       }
 
        regs [X86_EAX] = eax;
        regs [X86_ECX] = ecx;
@@ -196,10 +187,16 @@ x86_aot_trampoline (int eax, int ecx, int edx, int esi, int edi,
        vtable_slot = mono_arch_get_vcall_slot_addr (code, (gpointer*)regs);
        g_assert (vtable_slot);
 
-       if (method->klass->valuetype)
-               addr = get_unbox_trampoline (method, addr);
+       is_got_entry = mono_aot_is_got_entry (code, (guint8*)vtable_slot);
+
+       if (!is_got_entry) {
+               if (!method)
+                       method = mono_get_method (image, token, NULL);
+               if (method->klass->valuetype)
+                       addr = get_unbox_trampoline (method, addr);
+       }
 
-       if (mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
+       if (is_got_entry || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
                *vtable_slot = addr;
 
        return addr;
@@ -247,8 +244,7 @@ x86_class_init_trampoline (int eax, int ecx, int edx, int esi, int edi,
 
                        /* Then atomically change the first 4 bytes to a nop as well */
                        ops = 0x90909090;
-                       InterlockedExchange ((guint32*)code, ops);
-
+                       InterlockedExchange ((gint32*)code, ops);
 #ifdef HAVE_VALGRIND_MEMCHECK_H
                        /* FIXME: the calltree skin trips on the self modifying code above */
 
@@ -261,8 +257,20 @@ x86_class_init_trampoline (int eax, int ecx, int edx, int esi, int edi,
                ;
        } else if ((code [-1] == 0xff) && (x86_modrm_reg (code [0]) == 0x2)) {
                /* call *<OFFSET>(<REG>) -> Call made from AOT code */
-               /* FIXME: Patch up the trampoline */
-               ;
+               int regs [X86_NREG];
+               gpointer *vtable_slot;
+
+               regs [X86_EAX] = eax;
+               regs [X86_ECX] = ecx;
+               regs [X86_EDX] = edx;
+               regs [X86_ESI] = esi;
+               regs [X86_EDI] = edi;
+               regs [X86_EBX] = ebx;
+
+               vtable_slot = mono_arch_get_vcall_slot_addr (code + 5, (gpointer*)regs);
+               g_assert (vtable_slot);
+
+               *vtable_slot = nullified_class_init_trampoline;
        } else {
                        printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
                                code [4], code [5], code [6]);
@@ -270,14 +278,10 @@ x86_class_init_trampoline (int eax, int ecx, int edx, int esi, int edi,
                }
 }
 
-static guchar*
-create_trampoline_code (MonoTrampolineType tramp_type)
+guchar*
+mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
 {
        guint8 *buf, *code;
-       static guint8 *trampoline_code [16];
-
-       if (trampoline_code [tramp_type])
-               return trampoline_code [tramp_type];
 
        code = buf = mono_global_codeman_reserve (256);
 
@@ -364,22 +368,23 @@ create_trampoline_code (MonoTrampolineType tramp_type)
 
        g_assert ((buf - code) <= 256);
 
-       if (tramp_type == MONO_TRAMPOLINE_GENERIC)
-               mono_generic_trampoline_code = code;
-       trampoline_code [tramp_type] = code;
+       if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
+               /* Initialize the nullified class init trampoline used in the AOT case */
+               nullified_class_init_trampoline = buf = mono_global_codeman_reserve (16);
+               x86_ret (buf);
+       }
 
        return code;
 }
 
 #define TRAMPOLINE_SIZE 10
 
-static MonoJitInfo*
-create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain)
+static gpointer
+create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
 {
        guint8 *code, *buf, *tramp;
-       MonoJitInfo *ji;
        
-       tramp = create_trampoline_code (tramp_type);
+       tramp = mono_get_trampoline_code (tramp_type);
 
        mono_domain_lock (domain);
        code = buf = mono_code_manager_reserve (domain->code_mp, TRAMPOLINE_SIZE);
@@ -389,23 +394,30 @@ create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDo
        x86_jump_code (buf, tramp);
        g_assert ((buf - code) <= TRAMPOLINE_SIZE);
 
-       ji = g_new0 (MonoJitInfo, 1);
-       ji->code_start = code;
-       ji->code_size = buf - code;
-
-       mono_arch_flush_icache (ji->code_start, ji->code_size);
+       mono_arch_flush_icache (code, buf - code);
 
        mono_jit_stats.method_trampolines++;
 
-       return ji;
+       if (code_len)
+               *code_len = buf - code;
+
+       return code;
 }
 
 MonoJitInfo*
 mono_arch_create_jump_trampoline (MonoMethod *method)
 {
-       MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get ());
+       MonoJitInfo *ji;
+       gpointer code;
+       guint32 code_size;
+
+       code = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get (), &code_size);
 
+       ji = g_new0 (MonoJitInfo, 1);
+       ji->code_start = code;
+       ji->code_size = code_size;
        ji->method = method;
+
        return ji;
 }
 
@@ -423,22 +435,13 @@ mono_arch_create_jump_trampoline (MonoMethod *method)
 gpointer
 mono_arch_create_jit_trampoline (MonoMethod *method)
 {
-       MonoJitInfo *ji;
-       gpointer code_start;
-
-       ji = create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC, mono_domain_get ());
-       code_start = ji->code_start;
-       g_free (ji);
-
-       return code_start;
+       return create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC, mono_domain_get (), NULL);
 }
 
 gpointer
 mono_arch_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
 {
        MonoDomain *domain = mono_domain_get ();
-       MonoJitInfo *ji;
-       gpointer code_start;
        guint8 *buf, *start;
 
        mono_domain_lock (domain);
@@ -449,11 +452,7 @@ mono_arch_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
        buf += sizeof (gpointer);
        *(guint32*)buf = token;
 
-       ji = create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain);
-       code_start = ji->code_start;
-       g_free (ji);
-
-       return code_start;
+       return create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain, NULL);
 }
 
 /**
@@ -470,14 +469,7 @@ mono_arch_create_jit_trampoline_from_token (MonoImage *image, guint32 token)
 gpointer
 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
 {
-       MonoJitInfo *ji;
-       gpointer code;
-
-       ji = create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain);
-       code = ji->code_start;
-       g_free (ji);
-
-       return code;
+       return create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain, NULL);
 }
 
 void
@@ -507,11 +499,3 @@ mono_debugger_create_notification_function (gpointer *notification_address)
 
        return ptr;
 }
-
-void
-mono_x86_tramp_init (void)
-{
-       create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
-       create_trampoline_code (MONO_TRAMPOLINE_JUMP);
-       create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
-}