X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-sparc.c;h=f55c8bc7675d3356e6afcabbd5a34370bf1a2a30;hb=e72fb17dd374a2ee23aa946c39c2b56c2a7d9b07;hp=33402621f00b39ace73ad8fa4eb3f33cf85031e5;hpb=98abbb92daf3d5166c0833ebee82468ad4270263;p=mono.git diff --git a/mono/mini/tramp-sparc.c b/mono/mini/tramp-sparc.c index 33402621f00..f55c8bc7675 100644 --- a/mono/mini/tramp-sparc.c +++ b/mono/mini/tramp-sparc.c @@ -1,5 +1,5 @@ /* - * tramp-sparc.c: JIT trampoline code for Sparc 64 + * tramp-sparc.c: JIT trampoline code for Sparc * * Authors: * Mark Crichton (crichton@gimp.org) @@ -15,28 +15,12 @@ #include #include #include -#include #include "mini.h" #include "mini-sparc.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 Sparc 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: + * mono_arch_get_unbox_trampoline: * @m: method pointer * @addr: pointer to native code for @m * @@ -44,16 +28,16 @@ guint8 *mono_generic_trampoline_code = NULL; * this argument. This method returns a pointer to a trampoline which does * unboxing before calling the method */ -static gpointer -get_unbox_trampoline (MonoMethod *m, gpointer addr) +gpointer +mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) { guint8 *code, *start; int this_pos = 4, reg; - 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 = 8; - start = code = g_malloc (36); + start = code = mono_global_codeman_reserve (36); /* This executes in the context of the caller, hence o0 */ sparc_add_imm (code, 0, sparc_o0, sizeof (MonoObject), sparc_o0); @@ -73,92 +57,50 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr) return start; } -/** - * sparc_magic_trampoline: - * @m: the method to translate - * @code: the address of the call instruction - * @fp: address of the stack frame for the caller - * - * This method is called by the trampoline functions for methods. It calls the - * JIT compiler to compile the method, then patches the calling instruction so - * further calls will bypass the trampoline. For virtual methods, it finds the - * address of the vtable slot and updates it. - */ -static gpointer -sparc_magic_trampoline (MonoMethod *m, guint32 *code, guint32 *fp) +void +mono_arch_patch_callsite (guint8 *code, guint8 *addr) { - gpointer addr; - gpointer *vtable_slot; - - addr = mono_compile_method (m); - g_assert (addr); - - /* - * Check whenever this is a virtual call, and call an unbox trampoline if - * needed. - */ - if (mono_sparc_is_virtual_call (code)) { - if (m->klass->valuetype) - addr = get_unbox_trampoline (m, addr); - - /* Compute address of vtable slot */ - vtable_slot = mono_sparc_get_vcall_slot_addr (code, fp); - *vtable_slot = addr; - } - else { - /* Patch calling code */ - if (sparc_inst_op (*code) == 0x1) { - MonoJitInfo *ji = - mono_jit_info_table_find (mono_domain_get (), code); - MonoJitInfo *target_ji = - mono_jit_info_table_find (mono_domain_get (), addr); - - if (mono_method_same_domain (ji, target_ji)) { - sparc_call_simple (code, (guint8*)addr - (guint8*)code); - } - } + if (sparc_inst_op (*code) == 0x1) { + sparc_call_simple (code, (guint8*)addr - (guint8*)code); } - - return addr; } -static void -sparc_class_init_trampoline (MonoVTable *vtable, guint32 *code) +void +mono_arch_patch_plt_entry (guint8 *code, guint8 *addr) { - mono_runtime_class_init (vtable); + g_assert_not_reached (); +} +void +mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs) +{ /* Patch calling code */ sparc_nop (code); } +void +mono_arch_nullify_plt_entry (guint8 *code) +{ + g_assert_not_reached (); +} + #define ALIGN_TO(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) -static guchar* -create_trampoline_code (MonoTrampolineType tramp_type) +guchar* +mono_arch_create_trampoline_code (MonoTrampolineType tramp_type) { guint8 *buf, *code, *tramp_addr; - guint32 lmf_offset, method_reg, i; - static guint8* generic_jump_trampoline = NULL; - static guint8 *generic_class_init_trampoline = NULL; - - 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; - } + guint32 lmf_offset, regs_offset, method_reg, i; + gboolean has_caller; - code = buf = g_malloc (512); + if (tramp_type == MONO_TRAMPOLINE_JUMP) + has_caller = FALSE; + else + has_caller = TRUE; - sparc_save_imm (code, sparc_sp, -608, sparc_sp); + code = buf = mono_global_codeman_reserve (1024); + + sparc_save_imm (code, sparc_sp, -1608, sparc_sp); #ifdef SPARCV9 method_reg = sparc_g4; @@ -198,16 +140,36 @@ create_trampoline_code (MonoTrampolineType tramp_type) code = mono_sparc_emit_save_lmf (code, lmf_offset); + regs_offset = MONO_SPARC_STACK_BIAS + 1000; + + if (has_caller) { + /* Load all registers of the caller into a table inside this frame */ + /* first the out registers */ + for (i = 0; i < 8; ++i) + sparc_sti_imm (code, sparc_i0 + i, sparc_sp, regs_offset + (i * sizeof (gpointer))); + /* then the in+local registers */ + for (i = 0; i < 16; i ++) { + sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS + (i * sizeof (gpointer)), sparc_o7); + sparc_sti_imm (code, sparc_o7, sparc_sp, regs_offset + ((i + 8) * sizeof (gpointer))); + } + } + if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) - tramp_addr = &sparc_class_init_trampoline; + tramp_addr = &mono_class_init_trampoline; + else if (tramp_type == MONO_TRAMPOLINE_AOT) + tramp_addr = mono_aot_trampoline; else - tramp_addr = &sparc_magic_trampoline; - sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 200, sparc_o0); - /* pass parent frame address as third argument */ - sparc_mov_reg_reg (code, sparc_fp, sparc_o2); + tramp_addr = &mono_magic_trampoline; + sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 200, sparc_o2); + /* pass address of register table as third argument */ + sparc_add_imm (code, FALSE, sparc_sp, regs_offset, sparc_o0); sparc_set (code, tramp_addr, sparc_o7); /* set %o1 to caller address */ - sparc_mov_reg_reg (code, sparc_i7, sparc_o1); + if (has_caller) + sparc_mov_reg_reg (code, sparc_i7, sparc_o1); + else + sparc_set (code, 0, sparc_o1); + sparc_set (code, 0, sparc_o3); sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7); sparc_nop (code); @@ -257,18 +219,6 @@ create_trampoline_code (MonoTrampolineType tramp_type) g_assert ((code - buf) <= 512); - switch (tramp_type) { - case MONO_TRAMPOLINE_GENERIC: - mono_generic_trampoline_code = buf; - break; - case MONO_TRAMPOLINE_JUMP: - generic_jump_trampoline = buf; - break; - case MONO_TRAMPOLINE_CLASS_INIT: - generic_class_init_trampoline = buf; - break; - } - mono_arch_flush_icache (buf, code - buf); return buf; @@ -276,13 +226,12 @@ create_trampoline_code (MonoTrampolineType tramp_type) #define TRAMPOLINE_SIZE (((SPARC_SET_MAX_SIZE >> 2) * 2) + 2) -static MonoJitInfo* -create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain) +gpointer +mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) { - MonoJitInfo *ji; guint32 *code, *buf, *tramp; - 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 * 4); @@ -300,85 +249,25 @@ create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDo g_assert ((code - buf) <= TRAMPOLINE_SIZE); - ji = g_new0 (MonoJitInfo, 1); - ji->code_start = buf; - ji->code_size = (code - buf) * 4; + if (code_len) + *code_len = (code - buf) * 4; mono_jit_stats.method_trampolines++; - mono_arch_flush_icache (ji->code_start, ji->code_size); + mono_arch_flush_icache (buf, (code - buf) * 4); - return ji; + return buf; } -MonoJitInfo* -mono_arch_create_jump_trampoline (MonoMethod *method) -{ - MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get ()); - - ji->method = method; - return ji; -} - -/** - * mono_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. I also replaces the - * corresponding vtable entry (see sparc_magic_trampoline). - * - * Returns: a pointer to the newly created code - */ -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; -} - -/** - * 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) -{ - MonoJitInfo *ji; - gpointer code; - - ji = create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain); - code = ji->code_start; - g_free (ji); - - return code; -} - /* * This method is only called when running in the Mono Debugger. */ gpointer -mono_debugger_create_notification_function (gpointer *notification_address) +mono_debugger_create_notification_function (MonoCodeManager *codeman) { guint8 *ptr, *buf; - ptr = buf = g_malloc0 (16); - if (notification_address) - *notification_address = buf; + ptr = buf = mono_code_manager_reserve (codeman, 16); g_assert_not_reached ();