X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-s390.c;h=fe465ef6a9e097d064473d630aa9aa94a5b3ed9d;hb=a5c91be9e97bec871a4b5ec276e34c172620d6cc;hp=300a3703a7132fba841c3ff61b81950330acc6e5;hpb=bd13a9521bd74949d45fdfe98b1c02e8d73e1ceb;p=mono.git diff --git a/mono/mini/tramp-s390.c b/mono/mini/tramp-s390.c index 300a3703a71..fe465ef6a9e 100644 --- a/mono/mini/tramp-s390.c +++ b/mono/mini/tramp-s390.c @@ -1,10 +1,49 @@ -/* - * tramp-s390.c: JIT trampoline code for S/390 - * - * Authors: - * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) - * - */ +/*------------------------------------------------------------------*/ +/* */ +/* Name - tramp-s390.c */ +/* */ +/* Function - JIT trampoline code for S/390. */ +/* */ +/* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */ +/* */ +/* Date - January, 2004 */ +/* */ +/* Derivation - From exceptions-x86 & exceptions-ppc */ +/* Paolo Molaro (lupus@ximian.com) */ +/* Dietmar Maurer (dietmar@ximian.com) */ +/* */ +/* Copyright - 2001 Ximian, Inc. */ +/* */ +/*------------------------------------------------------------------*/ + +/*------------------------------------------------------------------*/ +/* D e f i n e s */ +/*------------------------------------------------------------------*/ + +#define GR_SAVE_SIZE 4*sizeof(long) +#define FP_SAVE_SIZE 16*sizeof(double) +#define CREATE_STACK_SIZE (S390_MINIMAL_STACK_SIZE+GR_SAVE_SIZE+FP_SAVE_SIZE+2*sizeof(long)) +#define CREATE_GR_OFFSET S390_MINIMAL_STACK_SIZE +#define CREATE_FP_OFFSET CREATE_GR_OFFSET+GR_SAVE_SIZE +#define CREATE_LMF_OFFSET CREATE_FP_OFFSET+FP_SAVE_SIZE +#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 */ +/*------------------------------------------------------------------*/ +#define METHOD_TRAMPOLINE_SIZE 64 +#define JUMP_TRAMPOLINE_SIZE 64 + +/*========================= End of Defines =========================*/ + +/*------------------------------------------------------------------*/ +/* I n c l u d e s */ +/*------------------------------------------------------------------*/ #include #include @@ -19,38 +58,54 @@ #include "mini.h" #include "mini-s390.h" +/*========================= End of Includes ========================*/ + +/*------------------------------------------------------------------*/ +/* T y p e d e f s */ +/*------------------------------------------------------------------*/ + typedef enum { MONO_TRAMPOLINE_GENERIC, MONO_TRAMPOLINE_JUMP, MONO_TRAMPOLINE_CLASS_INIT } MonoTrampolineType; -#define GR_SAVE_SIZE 4*sizeof(long) -#define FP_SAVE_SIZE 16*sizeof(double) -#define CREATE_STACK_SIZE (S390_MINIMAL_STACK_SIZE+GR_SAVE_SIZE+FP_SAVE_SIZE+2*sizeof(long)) -#define CREATE_GR_OFFSET S390_MINIMAL_STACK_SIZE -#define CREATE_FP_OFFSET CREATE_GR_OFFSET+GR_SAVE_SIZE -#define CREATE_LMF_OFFSET CREATE_FP_OFFSET+FP_SAVE_SIZE -#define METHOD_SAVE_OFFSET S390_RET_ADDR_OFFSET-4 +/*========================= End of Typedefs ========================*/ -/* adapt to mini later... */ -#define mono_jit_share_code (1) +/*------------------------------------------------------------------*/ +/* 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. - */ +/*------------------------------------------------------------------*/ +/* 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; -/* - * get_unbox_trampoline: - * @m: method pointer - * @addr: pointer to native code for @m - * - * when value type methods are called through the vtable we need to unbox the - * this argument. This method returns a pointer to a trampoline which does - * unboxing before calling the method - */ +/*========================= End of Prototypes ======================*/ + +/*------------------------------------------------------------------*/ +/* G l o b a l V a r i a b l e s */ +/*------------------------------------------------------------------*/ + + +/*====================== End of Global Variables ===================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - get_unbox_trampoline */ +/* */ +/* Function - Return a pointer to a trampoline which does the */ +/* unboxing before calling the method. */ +/* */ +/* When value type methods are called through the */ +/* vtable we need to unbox the 'this' argument. */ +/* */ +/* Parameters - method - Methd pointer */ +/* addr - Pointer to native code for method */ +/* */ +/*------------------------------------------------------------------*/ + static gpointer get_unbox_trampoline (MonoMethod *method, gpointer addr) { @@ -80,28 +135,32 @@ get_unbox_trampoline (MonoMethod *method, gpointer addr) return start; } -/* Method-specific trampoline code framgment size */ -#define METHOD_TRAMPOLINE_SIZE 64 - -/** - * s390_magic_trampoline: - * @code: pointer into caller code - * @method: the method to translate - * @sp: stack pointer - * - * This method is called by the function 'arch_create_jit_trampoline', which in - * turn is called by the trampoline functions for virtual methods. - * After having called the JIT compiler to compile the method, it inspects the - * caller code to find the address of the method-specific part of the - * trampoline vtable slot for this method, updates it with a fragment that calls - * the newly compiled code and returns this address of the compiled code to - * 'arch_create_jit_trampoline' - * The calls generated by mono for s/390 will look like either: - * 1. l %r1,xxx(%rx) - * bras %r14,%r1 - * or - * 2. brasl %r14,xxxxxx - */ +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - s390_magic_trampoline */ +/* */ +/* Function - This method is called by the function */ +/* "arch_create_jit_trampoline", which in turn is */ +/* called by the trampoline functions for virtual */ +/* methods. After having called the JIT compiler to */ +/* compile the method, it inspects the caller code */ +/* to find the address of the method-specific part */ +/* of the trampoline vtable slot for this method, */ +/* updates it with a fragment that calls the newly */ +/* compiled code and returns this address. The calls */ +/* generated by mono for S/390 will look like either:*/ +/* 1. l %r1,xxx(%rx) */ +/* bras %r14,%r1 */ +/* 2. brasl %r14,xxxxxx */ +/* */ +/* Parameters - code - Pointer into caller code */ +/* method - The method to compile */ +/* sp - Stack pointer */ +/* */ +/*------------------------------------------------------------------*/ + static gpointer s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp) { @@ -114,43 +173,58 @@ s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp) addr = mono_compile_method(method); g_assert(addr); - /* The top bit needs to be ignored on S/390 */ - (guint32) code &= 0x7fffffff; - - fname = mono_method_full_name (method, TRUE); - - 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); - code = base + displace; - s390_patch(code, addr); - break; - case 0xc0e5 : - /* This is the 'brasl' instruction */ - code -= 4; - displace = ((gint32) addr - (gint32) (code - 2)) / 2; - s390_patch (code, displace); - mono_arch_flush_icache (code, 4); - break; - default : - g_error("Unable to patch instruction prior to %p",code); + + if (code) { + + /* The top bit needs to be ignored on S/390 */ + (guint32) code &= 0x7fffffff; + + fname = mono_method_full_name (method, TRUE); + + 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); + code = base + displace; + s390_patch(code, addr); + break; + case 0xc0e5 : + /* This is the 'brasl' instruction */ + code -= 4; + displace = ((gint32) addr - (gint32) (code - 2)) / 2; + s390_patch (code, displace); + mono_arch_flush_icache (code, 4); + break; + default : + g_error("Unable to patch instruction prior to %p",code); + } } return addr; } +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - s390_class_init_trampoline */ +/* */ +/* Function - Initialize a class and then no-op the call to */ +/* the trampoline. */ +/* */ +/*------------------------------------------------------------------*/ + static void s390_class_init_trampoline (void *vtable, guchar *code, char *sp) { @@ -163,6 +237,17 @@ s390_class_init_trampoline (void *vtable, guchar *code, char *sp) memcpy(code, patch, sizeof(patch)); } +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - create_trampoline_code */ +/* */ +/* Function - Create the designated type of trampoline according*/ +/* to the 'tramp_type' parameter. */ +/* */ +/*------------------------------------------------------------------*/ + static guchar* create_trampoline_code (MonoTrampolineType tramp_type) { @@ -236,11 +321,7 @@ create_trampoline_code (MonoTrampolineType tramp_type) /* Arg 1: MonoMethod *method. It was put in r11 by the method-specific trampoline code, and then saved before the call to mono_get_lmf_addr()'. Restore r13, by the way :-) */ - if (tramp_type == MONO_TRAMPOLINE_JUMP) { - s390_lhi (buf, s390_r2, 0); - } else { - s390_l (buf, s390_r2, 0, s390_r11, METHOD_SAVE_OFFSET); - } + s390_l (buf, s390_r2, 0, s390_r11, METHOD_SAVE_OFFSET); /* Arg 2: code (next address to the instruction that called us) */ if (tramp_type == MONO_TRAMPOLINE_JUMP) { @@ -318,25 +399,82 @@ create_trampoline_code (MonoTrampolineType tramp_type) return code; } -/** - * arch_create_jit_trampoline: - * @method: pointer to the method info - * - * Creates a trampoline function for virtual methods. If the created - * code is called it first starts JIT compilation of method, - * and then calls the newly created method. It also replaces the - * corresponding vtable entry (see s390_magic_trampoline). - * - * A trampoline consists of two parts: a main fragment, shared by all method - * trampolines, and some code specific to each method, which hard-codes a - * reference to that method and then calls the main fragment. - * - * The main fragment contains a call to 's390_magic_trampoline', which performs - * call to the JIT compiler and substitutes the method-specific fragment with - * some code that directly calls the JIT-compiled method. - * - * Returns: a pointer to the newly created code - */ +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_jump_trampoline */ +/* */ +/* Function - Create the designated type of trampoline according*/ +/* to the 'tramp_type' parameter. */ +/* */ +/*------------------------------------------------------------------*/ + +MonoJitInfo * +mono_arch_create_jump_trampoline (MonoMethod *method) +{ + guint8 *code, *buf, *tramp = NULL; + MonoJitInfo *ji; + MonoDomain *domain = mono_domain_get(); + gint32 displace; + + tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP); + + mono_domain_lock (domain); + code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE); + mono_domain_unlock (domain); + + s390_basr (buf, s390_r13, 0); + s390_j (buf, 4); + s390_word (buf, method); + s390_l (buf, s390_r13, 0, s390_r13, 4); + displace = (tramp - buf) / 2; + s390_jcl (buf, S390_CC_UN, displace); + + mono_arch_flush_icache (code, buf-code); + + g_assert ((buf - code) <= JUMP_TRAMPOLINE_SIZE); + + ji = g_new0 (MonoJitInfo, 1); + ji->method = method; + ji->code_start = code; + ji->code_size = buf - code; + + mono_jit_stats.method_trampolines++; + + return ji; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_jit_trampoline */ +/* */ +/* Function - Creates a trampoline function for virtual methods.*/ +/* If the created code is called it first starts JIT */ +/* compilation and then calls the newly created */ +/* method. It also replaces the corresponding vtable */ +/* entry (see s390_magic_trampoline). */ +/* */ +/* A trampoline consists of two parts: a main */ +/* fragment, shared by all method trampolines, and */ +/* and some code specific to each method, which */ +/* hard-codes a reference to that method and then */ +/* calls the main fragment. */ +/* */ +/* The main fragment contains a call to */ +/* 's390_magic_trampoline', which performs a call */ +/* to the JIT compiler and substitutes the method- */ +/* specific fragment with some code that directly */ +/* calls the JIT-compiled method. */ +/* */ +/* Parameter - method - Pointer to the method information */ +/* */ +/* Returns - A pointer to the newly created code */ +/* */ +/*------------------------------------------------------------------*/ + gpointer mono_arch_create_jit_trampoline (MonoMethod *method) { @@ -344,13 +482,6 @@ mono_arch_create_jit_trampoline (MonoMethod *method) static guint8 *vc = NULL; gint32 displace; - /* 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)); - vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC); /* This is the method-specific part of the trampoline. Its purpose is @@ -373,26 +504,29 @@ mono_arch_create_jit_trampoline (MonoMethod *method) /* Sanity check */ g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE); - /* Store trampoline address */ - method->info = code; - mono_jit_stats.method_trampolines++; return code; } +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_class_init_trampoline */ +/* */ +/* Function - Creates a trampoline function to run a type init- */ +/* ializer. If the trampoline is called, it calls */ +/* mono_runtime_class_init with the given vtable, */ +/* then patches the caller code so it does not get */ +/* called any more. */ +/* */ +/* Parameter - vtable - The type to initialize */ +/* */ +/* Returns - A pointer to the newly created code */ +/* */ +/*------------------------------------------------------------------*/ -/** - * mono_arch_create_class_init_trampoline: - * @vtable: the type to initialize - * - * Creates a trampoline function to run a type initializer. - * If the trampoline is called, it calls mono_runtime_class_init with the - * given vtable, then patches the caller code so it does not get called any - * more. - * - * Returns: a pointer to the newly created code - */ gpointer mono_arch_create_class_init_trampoline (MonoVTable *vtable) { @@ -435,9 +569,18 @@ mono_arch_create_class_init_trampoline (MonoVTable *vtable) return code; } -/* - * This method is only called when running in the Mono Debugger. - */ +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_debuger_create_notification_function */ +/* */ +/* Function - This method is only called when running in the */ +/* Mono debugger. It returns a pointer to the */ +/* arch specific notification function. */ +/* */ +/*------------------------------------------------------------------*/ + gpointer mono_debugger_create_notification_function (gpointer *notification_address) { @@ -451,3 +594,5 @@ mono_debugger_create_notification_function (gpointer *notification_address) return ptr; } + +/*========================= End of Function ========================*/