2005-12-11 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / tramp-s390.c
index 77281803413b176d9a80ebb41f1bc6dd37439dab..47453ea4413a0a099689e00b2fd120a8de97cb1b 100644 (file)
 #define CREATE_STACK_SIZE      (CREATE_LMF_OFFSET+2*sizeof(long)+sizeof(MonoLMF))
 #define METHOD_SAVE_OFFSET     S390_RET_ADDR_OFFSET-4
 
-/*------------------------------------------------------------------*/
-/* adapt to mini later...                                          */
-/*------------------------------------------------------------------*/
-#define mono_jit_share_code    (1)
-
 /*------------------------------------------------------------------*/
 /* Method-specific trampoline code fragment sizes                  */
 /*------------------------------------------------------------------*/
 /*                 T y p e d e f s                                  */
 /*------------------------------------------------------------------*/
 
-typedef enum {
-       MONO_TRAMPOLINE_GENERIC,
-       MONO_TRAMPOLINE_JUMP,
-       MONO_TRAMPOLINE_CLASS_INIT
-} MonoTrampolineType;
-
 /*========================= End of Typedefs ========================*/
 
 /*------------------------------------------------------------------*/
 /*                   P r o t o t y p e s                            */
 /*------------------------------------------------------------------*/
 
-/*------------------------------------------------------------------*/
-/* Address of the generic trampoline code.  This is used by the     */
-/* debugger to check whether a method is a trampoline.             */
-/*------------------------------------------------------------------*/
-guint8 *mono_generic_trampoline_code = NULL;
-
 /*========================= End of Prototypes ======================*/
 
 /*------------------------------------------------------------------*/
@@ -113,24 +96,20 @@ get_unbox_trampoline (MonoMethod *method, gpointer addr)
        int this_pos = s390_r2;
 
        start = addr;
-       if ((method->klass->valuetype)) {
-//     if ((method->klass->valuetype) && 
-//         (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
-               if ((!method->signature->ret->byref) && 
-                   (MONO_TYPE_ISSTRUCT (method->signature->ret)))
-                       this_pos = s390_r3;
-           
-               start = code = g_malloc (28);
-
-               s390_basr (code, s390_r13, 0);
-               s390_j    (code, 4);
-               s390_word (code, addr);
-               s390_l    (code, s390_r1, 0, s390_r13, 4);
-               s390_ahi  (code, this_pos, sizeof(MonoObject));
-               s390_br   (code, s390_r1);
-
-               g_assert ((code - start) <= 28);
-       }
+       if ((!mono_method_signature (method)->ret->byref) && 
+           (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)))
+               this_pos = s390_r3;
+    
+       start = code = mono_global_codeman_reserve (28);
+
+       s390_basr (code, s390_r13, 0);
+       s390_j    (code, 4);
+       s390_word (code, addr);
+       s390_l    (code, s390_r1, 0, s390_r13, 4);
+       s390_ahi  (code, this_pos, sizeof(MonoObject));
+       s390_br   (code, s390_r1);
+
+       g_assert ((code - start) <= 28);
 
        return start;
 }
@@ -166,7 +145,8 @@ s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp)
 {
        gpointer addr;
        gint32 displace;
-       int reg, base;
+       int reg;
+       guchar* base;
        unsigned short opcode;
        char *fname;
        MonoJitInfo *codeJi, 
@@ -179,42 +159,48 @@ s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp)
        if (code) {
 
                /* The top bit needs to be ignored on S/390 */
-               (guint32) code &= 0x7fffffff;
+               code = (guchar*)((guint32)code & 0x7fffffff);
 
                fname  = mono_method_full_name (method, TRUE);
                codeJi = mono_jit_info_table_find (mono_domain_get(), code);
                addrJi = mono_jit_info_table_find (mono_domain_get(), addr);
+               if (mono_method_same_domain (codeJi, addrJi)) {
+
+                       opcode = *((unsigned short *) (code - 6));
+                       switch (opcode) {
+                               case 0x5810 :
+                                       /* This is a bras r14,r1 instruction */
+                                       code    -= 4;
+                                       reg      = *code >> 4;
+                                       displace = *((short *)code) & 0x0fff;
+                                       if (reg > 5) 
+                                               base = *((guchar **) (sp + S390_REG_SAVE_OFFSET+
+                                                                      sizeof(int)*(reg-6)));
+                                       else
+                                               base = *((guchar **) (sp + CREATE_GR_OFFSET+
+                                                                      sizeof(int)*(reg-2)));
+
+                                       if ((method->klass->valuetype) && 
+                                           (!mono_aot_is_got_entry(code, base))) 
+                                               addr = get_unbox_trampoline(method, addr);
 
-               opcode = *((unsigned short *) (code - 6));
-               switch (opcode) {
-                       case 0x5810 :
-                               /* This is a bras r14,r1 instruction */
-                               code    -= 4;
-                               reg      = *code >> 4;
-                               displace = *((short *)code) & 0x0fff;
-                               if (reg > 5) 
-                                       base = *((int *) (sp + S390_REG_SAVE_OFFSET+
-                                                              sizeof(int)*(reg-6)));
-                               else
-                                       base = *((int *) (sp + CREATE_GR_OFFSET+
-                                                              sizeof(int)*(reg-2)));
-                               addr = get_unbox_trampoline(method, addr);
-                               if (mono_method_same_domain (codeJi, addrJi)) {
                                        code = base + displace;
-                                       s390_patch(code, addr);
-                               }
-                               break;
-                       case 0xc0e5 :
-                               /* This is the 'brasl' instruction */
-                               code    -= 4;
-                               displace = ((gint32) addr - (gint32) (code - 2)) / 2;
-                               if (mono_method_same_domain (codeJi, addrJi)) {
-                                       s390_patch (code, displace);
-                                       mono_arch_flush_icache (code, 4);
-                               }
-                               break;
-                       default :
-                               g_error("Unable to patch instruction prior to %p",code);
+                                       if (mono_domain_owns_vtable_slot(mono_domain_get(), 
+                                                                        code))
+                                               s390_patch(code, addr);
+                                       break;
+                               case 0xc0e5 :
+                                       /* This is the 'brasl' instruction */
+                                       code    -= 4;
+                                       displace = ((gint32) addr - (gint32) (code - 2)) / 2;
+                                       if (mono_method_same_domain (codeJi, addrJi)) {
+                                               s390_patch (code, displace);
+                                               mono_arch_flush_icache (code, 4);
+                                       }
+                                       break;
+                               default :
+                                       g_error("Unable to patch instruction prior to %p",code);
+                       }
                }
        }
 
@@ -249,42 +235,25 @@ s390_class_init_trampoline (void *vtable, guchar *code, char *sp)
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - create_trampoline_code                            */
+/* Name                - mono_arch_create_trampoline_code                            */
 /*                                                                  */
 /* Function    - Create the designated type of trampoline according*/
 /*                to the 'tramp_type' parameter.                    */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
-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, lmfOffset;
 
-       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 S/390 trampoline code. This
                 is the trampoline code common to all methods  */
                
-               code = buf = g_malloc(512);
+               code = buf = mono_global_codeman_reserve(512);
                
                /*-----------------------------------------------------------
                STEP 0: First create a non-standard function prologue with a
@@ -354,12 +323,16 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                s390_l     (buf, s390_r1, 0, s390_r11, METHOD_SAVE_OFFSET);
                s390_st    (buf, s390_r1, 0, s390_r13,                          
                            G_STRUCT_OFFSET(MonoLMF, method));                          
-                                                                               
+                                                                       
                /*---------------------------------------------------------------*/     
-               /* save the current IP                                           */     
+               /* save the current SP                                           */     
                /*---------------------------------------------------------------*/     
                s390_l     (buf, s390_r1, 0, STK_BASE, 0);
                s390_st    (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));  
+                                                                       
+               /*---------------------------------------------------------------*/     
+               /* save the current IP                                           */     
+               /*---------------------------------------------------------------*/     
                if (tramp_type == MONO_TRAMPOLINE_JUMP) {
                        s390_lhi   (buf, s390_r1, 0);
                } else {
@@ -420,7 +393,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                STEP 3: Restore the LMF
                ----------------------------------------------------------*/
                restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE);
-               
+       
                /*----------------------------------------------------------
                STEP 4: call the compiled method
                ----------------------------------------------------------*/
@@ -449,18 +422,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;
 }
 
@@ -483,7 +444,7 @@ mono_arch_create_jump_trampoline (MonoMethod *method)
        MonoDomain *domain = mono_domain_get();
        gint32 displace;
 
-       tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
+       tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
 
        mono_domain_lock (domain);
        code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
@@ -547,14 +508,14 @@ mono_arch_create_jit_trampoline (MonoMethod *method)
        static guint8 *vc = NULL;
        gint32 displace;
 
-       vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
+       vc = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC);
 
        /* This is the method-specific part of the trampoline. Its purpose is
        to provide the generic part with the MonoMethod *method pointer. We'll
        use r13 to keep that value, for instance. However, the generic part of
        the trampoline relies on r11 having the same value it had before coming
        here, so we must save it before. */
-       code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
+       code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE);
 
        s390_basr (buf, s390_r13, 0);
        s390_j    (buf, 4);
@@ -569,8 +530,6 @@ mono_arch_create_jit_trampoline (MonoMethod *method)
        /* Sanity check */
        g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
        
-       mono_jit_stats.method_trampolines++;
-
        return code;
 }
 
@@ -597,14 +556,17 @@ 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
-       use r11 to keep that value, for instance. However, the generic part of
-       the trampoline relies on r11 having the same value it had before coming
-       here, so we must save it before. */
-       code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
+       /*-----------------------------------------------------------*/
+       /* This is the method-specific part of the trampoline. Its   */
+       /* purpose is to provide the generic part with the MonoMethod*/
+       /* *method pointer. We'll use r11 to keep that value, for    */
+       /* instance. However, the generic part of the trampoline     */
+       /* relies on r11 having the same value it had before coming  */
+       /* here, so we must save it before.                          */
+       /*-----------------------------------------------------------*/
+       code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE);
 
        s390_st   (buf, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
        s390_ahi  (buf, STK_BASE, -S390_MINIMAL_STACK_SIZE);
@@ -651,7 +613,7 @@ mono_debugger_create_notification_function (gpointer *notification_address)
 {
        guint8 *ptr, *buf;
 
-       ptr = buf = g_malloc0 (16);
+       ptr = buf = mono_global_codeman_reserve (16);
        s390_break (buf);
        if (notification_address)
                *notification_address = buf;