2006-01-03 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / tramp-ppc.c
index b304600e59d9b217fd1c1c9dfd4cbedf37a92b11..33a2bb7ba345cc5e9cb9395dd84f36178a0ee29e 100644 (file)
 #include "mini.h"
 #include "mini-ppc.h"
 
-typedef enum {
-       MONO_TRAMPOLINE_GENERIC,
-       MONO_TRAMPOLINE_JUMP,
-       MONO_TRAMPOLINE_CLASS_INIT
-} 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;
-
 /*
  * get_unbox_trampoline:
  * @m: method pointer
@@ -51,7 +36,7 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr)
        guint8 *code, *start;
        int this_pos = 3;
 
-       if (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->ret))
+       if (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
                this_pos = 4;
            
        start = code = g_malloc (20);
@@ -101,6 +86,7 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
 {
        char *o = NULL;
        gpointer addr;
+        MonoJitInfo *ji, *target_ji;
        int reg, offset = 0;
 
        addr = mono_compile_method(method);
@@ -111,6 +97,12 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
                return addr;
        }
 
+       /* We can't trampoline across domains */
+       ji = mono_jit_info_table_find (mono_domain_get (), code);
+       target_ji = mono_jit_info_table_find (mono_domain_get (), addr);
+       if (!mono_method_same_domain (ji, target_ji))
+               return addr;
+
        /* Locate the address of the method-specific trampoline. The call using
        the vtable slot that took the processing flow to 'arch_create_jit_trampoline' 
        looks something like this:
@@ -146,7 +138,13 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
        
        /* Sanity check: instruction must be 'blrl' */
        g_assert(*code == 0x4e800021);
-       
+
+       /* the thunk-less direct call sequence: lis/ori/mtlr/blrl */
+       if ((code [-1] >> 26) == 31 && (code [-2] >> 26) == 24 && (code [-3] >> 26) == 15) {
+               ppc_patch ((char*)code, addr);
+               return addr;
+       }
+
        /* OK, we're now at the 'blrl' instruction. Now walk backwards
        till we get to a 'mtlr rA' */
        for(; --code;) {
@@ -185,11 +183,12 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
           we won't have an object, but the actual pointer to the 
           valuetype as the this argument
         */
-       if (method->klass->valuetype)
+       if (method->klass->valuetype && !mono_aot_is_got_entry (code, o))
                addr = get_unbox_trampoline (method, addr);
 
        o += offset;
-       *((gpointer *)o) = addr;
+       if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
+               *((gpointer *)o) = addr;
        return addr;
 }
 
@@ -227,29 +226,12 @@ ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
  *  linkage area
  *  -------------------
  */
-static guchar*
-create_trampoline_code (MonoTrampolineType tramp_type)
+guchar*
+mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
 {
        guint8 *buf, *code = NULL;
-       static guint8* generic_jump_trampoline = NULL;
-       static guint8 *generic_class_init_trampoline = NULL;
        int i, offset;
 
-       switch (tramp_type) {
-       case MONO_TRAMPOLINE_GENERIC:
-               if (mono_generic_trampoline_code)
-                       return mono_generic_trampoline_code;
-               break;
-       case MONO_TRAMPOLINE_JUMP:
-               if (generic_jump_trampoline)
-                       return generic_jump_trampoline;
-               break;
-       case MONO_TRAMPOLINE_CLASS_INIT:
-               if (generic_class_init_trampoline)
-                       return generic_class_init_trampoline;
-               break;
-       }
-
        if(!code) {
                /* Now we'll create in 'buf' the PowerPC trampoline code. This
                 is the trampoline code common to all methods  */
@@ -402,18 +384,6 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                g_assert ((buf - code) <= 512);
        }
 
-       switch (tramp_type) {
-       case MONO_TRAMPOLINE_GENERIC:
-               mono_generic_trampoline_code = code;
-               break;
-       case MONO_TRAMPOLINE_JUMP:
-               generic_jump_trampoline = code;
-               break;
-       case MONO_TRAMPOLINE_CLASS_INIT:
-               generic_class_init_trampoline = code;
-               break;
-       }
-
        return code;
 }
 
@@ -460,7 +430,7 @@ mono_arch_create_jump_trampoline (MonoMethod *method)
        guint8 *tramp;
        MonoDomain* domain = mono_domain_get ();
        
-       tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
+       tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
        return create_specific_tramp (method, tramp, domain);
 }
 
@@ -489,20 +459,15 @@ mono_arch_create_jit_trampoline (MonoMethod *method)
        guint8 *tramp;
        MonoJitInfo *ji;
        MonoDomain* domain = mono_domain_get ();
+       gpointer code_start;
 
-       /* previously created trampoline code */
-       if (method->info)
-               return method->info;
-
-       if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
-               return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
-
-       tramp = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
-       /* FIXME: should pass the domain down tot his function */
+       tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC);
+       /* FIXME: should pass the domain down to this function */
        ji = create_specific_tramp (method, tramp, domain);
-       /* Store trampoline address */
-       method->info = ji->code_start;
-       return ji->code_start;
+       code_start = ji->code_start;
+       g_free (ji);
+
+       return code_start;
 }
 
 /**
@@ -521,7 +486,7 @@ mono_arch_create_class_init_trampoline (MonoVTable *vtable)
 {
        guint8 *code, *buf, *tramp;
 
-       tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
+       tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
 
        /* This is the method-specific part of the trampoline. Its purpose is
        to provide the generic part with the MonoMethod *method pointer. We'll
@@ -572,6 +537,7 @@ mono_debugger_create_notification_function (gpointer *notification_address)
        if (notification_address)
                *notification_address = buf;
        ppc_blr (buf);
+       mono_arch_flush_icache (ptr, buf - ptr);
 
        return ptr;
 }