X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-x86.c;h=5d9f17dff5eddc5f61283b0bf0f170aabbca42ec;hb=8f09dad4353bb75afebf96ad58d08f7e7f3bf56d;hp=09dc882e07195a54f2c7db250b9fb6eccfba309f;hpb=01ea58cbd474d4a9230acbba5571738896539d42;p=mono.git diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c index 09dc882e071..5d9f17dff5e 100644 --- a/mono/mini/tramp-x86.c +++ b/mono/mini/tramp-x86.c @@ -25,8 +25,6 @@ #include "mini.h" #include "mini-x86.h" -static guint8* nullified_class_init_trampoline; - /* * mono_arch_get_unbox_trampoline: * @m: method pointer @@ -40,16 +38,16 @@ gpointer mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) { guint8 *code, *start; - int this_pos = 4; + int this_pos = 4, size = NACL_SIZE(16, 32); MonoDomain *domain = mono_domain_get (); - start = code = mono_domain_code_reserve (domain, 16); + start = code = mono_domain_code_reserve (domain, size); x86_alu_membase_imm (code, X86_ADD, X86_ESP, this_pos, sizeof (MonoObject)); x86_jump_code (code, addr); - g_assert ((code - start) < 16); + g_assert ((code - start) < size); - nacl_domain_code_validate (domain, &start, 16, &code); + nacl_domain_code_validate (domain, &start, size, &code); return start; } @@ -62,7 +60,7 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo MonoDomain *domain = mono_domain_get (); - buf_len = 10; + buf_len = NACL_SIZE (10, 32); start = code = mono_domain_code_reserve (domain, buf_len); @@ -239,6 +237,7 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) { guint8 buf [16]; gboolean can_write = mono_breakpoint_clean_code (NULL, code, 6, buf, sizeof (buf)); + gpointer tramp = mini_get_nullified_class_init_trampoline (); if (!can_write) return; @@ -273,7 +272,7 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) //VALGRIND_DISCARD_TRANSLATIONS (code, 8); } #elif defined(__native_client_codegen__) - mono_arch_patch_callsite (code, code + 5, nullified_class_init_trampoline); + mono_arch_patch_callsite (code, code + 5, tramp); #endif } else if (code [0] == 0x90 || code [0] == 0xeb) { /* Already changed by another thread */ @@ -285,7 +284,7 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) vtable_slot = get_vcall_slot_addr (code + 5, regs); g_assert (vtable_slot); - *vtable_slot = nullified_class_init_trampoline; + *vtable_slot = tramp; } 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]); @@ -293,18 +292,10 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) } } -void -mono_arch_nullify_plt_entry (guint8 *code, mgreg_t *regs) -{ - if (mono_aot_only && !nullified_class_init_trampoline) - nullified_class_init_trampoline = mono_aot_get_trampoline ("nullified_class_init_trampoline"); - - mono_arch_patch_plt_entry (code, NULL, regs, nullified_class_init_trampoline); -} - guchar* mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot) { + char *tramp_name; guint8 *buf, *code, *tramp; int pushed_args, pushed_args_caller_saved; GSList *unwind_ops = NULL; @@ -524,17 +515,22 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf g_assert (pushed_args == -1); } - x86_ret (code); + /*block guard trampolines are called with the stack aligned but must exit with the stack unaligned. */ + if (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD) { + x86_pop_reg (code, X86_EAX); + x86_alu_reg_imm (code, X86_ADD, X86_ESP, 0x8); + x86_jump_reg (code, X86_EAX); + } else { + x86_ret (code); + } nacl_global_codeman_validate (&buf, 256, &code); g_assert ((code - buf) <= 256); - if (info) - *info = mono_tramp_info_create (mono_get_generic_trampoline_name (tramp_type), buf, code - buf, ji, unwind_ops); - - if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) { - /* Initialize the nullified class init trampoline used in the AOT case */ - nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (NULL); + if (info) { + tramp_name = mono_get_generic_trampoline_name (tramp_type); + *info = mono_tramp_info_create (tramp_name, buf, code - buf, ji, unwind_ops); + g_free (tramp_name); } return buf; @@ -554,10 +550,7 @@ mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info) mono_arch_flush_icache (buf, code - buf); if (info) - *info = mono_tramp_info_create (g_strdup_printf ("nullified_class_init_trampoline"), buf, code - buf, NULL, NULL); - - if (mono_jit_map_is_enabled ()) - mono_emit_jit_tramp (buf, code - buf, "nullified_class_init_trampoline"); + *info = mono_tramp_info_create ("nullified_class_init_trampoline", buf, code - buf, NULL, NULL); return buf; } @@ -682,8 +675,53 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info g_assert (code - buf <= tramp_size); + if (info) { + char *name = mono_get_rgctx_fetch_trampoline_name (slot); + *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops); + g_free (name); + } + + return buf; +} + +/* + * mono_arch_create_general_rgctx_lazy_fetch_trampoline: + * + * This is a general variant of the rgctx fetch trampolines. It receives a pointer to gpointer[2] in the rgctx reg. The first entry contains the slot, the second + * the trampoline to call if the slot is not filled. + */ +gpointer +mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot) +{ + guint8 *code, *buf; + int tramp_size; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; + + g_assert (aot); + + unwind_ops = mono_arch_get_cie_program (); + + tramp_size = 64; + + code = buf = mono_global_codeman_reserve (tramp_size); + + // FIXME: Currently, we always go to the slow path. + + /* Load trampoline addr */ + x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_RGCTX_REG, 4, 4); + /* Load mrgctx/vtable */ + x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4); + + x86_jump_reg (code, X86_EAX); + + nacl_global_codeman_validate (&buf, tramp_size, &code); + mono_arch_flush_icache (buf, code - buf); + + g_assert (code - buf <= tramp_size); + if (info) - *info = mono_tramp_info_create (mono_get_rgctx_fetch_trampoline_name (slot), buf, code - buf, ji, unwind_ops); + *info = mono_tramp_info_create ("rgctx_fetch_trampoline_general", buf, code - buf, ji, unwind_ops); return buf; } @@ -740,7 +778,7 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a nacl_global_codeman_validate (&buf, tramp_size, &code); if (info) - *info = mono_tramp_info_create (g_strdup_printf ("generic_class_init_trampoline"), buf, code - buf, ji, unwind_ops); + *info = mono_tramp_info_create ("generic_class_init_trampoline", buf, code - buf, ji, unwind_ops); return buf; } @@ -817,7 +855,15 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) x86_branch8 (code, X86_CC_Z, -1, 1); /* load MonoInternalThread* into EDX */ - code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ()); + if (aot) { + /* load_aotconst () puts the result into EAX */ + x86_mov_reg_reg (code, X86_EDX, X86_EAX, sizeof (mgreg_t)); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_THREAD)); + code = mono_x86_emit_tls_get_reg (code, X86_EAX, X86_EAX); + x86_xchg_reg_reg (code, X86_EAX, X86_EDX, sizeof (mgreg_t)); + } else { + code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ()); + } /* load TID into EDX */ x86_mov_reg_membase (code, X86_EDX, X86_EDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 4); @@ -889,7 +935,7 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) nacl_global_codeman_validate (&buf, tramp_size, &code); if (info) - *info = mono_tramp_info_create (g_strdup_printf ("monitor_enter_trampoline"), buf, code - buf, ji, unwind_ops); + *info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops); return buf; } @@ -950,7 +996,15 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) /* next case: synchronization is not null */ /* load MonoInternalThread* into EDX */ - code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ()); + if (aot) { + /* load_aotconst () puts the result into EAX */ + x86_mov_reg_reg (code, X86_EDX, X86_EAX, sizeof (mgreg_t)); + code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_THREAD)); + code = mono_x86_emit_tls_get_reg (code, X86_EAX, X86_EAX); + x86_xchg_reg_reg (code, X86_EAX, X86_EDX, sizeof (mgreg_t)); + } else { + code = mono_x86_emit_tls_get (code, X86_EDX, mono_thread_get_tls_offset ()); + } /* load TID into EDX */ x86_mov_reg_membase (code, X86_EDX, X86_EDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 4); /* is synchronization->owner == TID */ @@ -1004,7 +1058,7 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) g_assert (code - buf <= tramp_size); if (info) - *info = mono_tramp_info_create (g_strdup_printf ("monitor_exit_trampoline"), buf, code - buf, ji, unwind_ops); + *info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops); return buf; } @@ -1037,48 +1091,57 @@ mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) x86_call_code (code, (guint8*)func); } -static void -handler_block_trampoline_helper (gpointer *ptr) +static gpointer +handler_block_trampoline_helper (void) { MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); - *ptr = jit_tls->handler_block_return_address; + return jit_tls->handler_block_return_address; } gpointer -mono_arch_create_handler_block_trampoline (void) +mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) { guint8 *tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD); guint8 *code, *buf; int tramp_size = 64; + MonoJumpInfo *ji = NULL; + GSList *unwind_ops = NULL; + + g_assert (!aot); + code = buf = mono_global_codeman_reserve (tramp_size); /* This trampoline restore the call chain of the handler block then jumps into the code that deals with it. */ + /* + * We are in a method frame after the call emitted by OP_CALL_HANDLER. + */ + if (mono_get_jit_tls_offset () != -1) { code = mono_x86_emit_tls_get (code, X86_EAX, mono_get_jit_tls_offset ()); x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 4); - /*simulate a call*/ - /*Fix stack alignment*/ - x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x8); - x86_push_reg (code, X86_EAX); - x86_jump_code (code, tramp); } else { /*Slow path uses a c helper*/ - x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x8); - x86_push_reg (code, X86_ESP); - x86_push_imm (code, tramp); - x86_jump_code (code, handler_block_trampoline_helper); + x86_call_code (code, handler_block_trampoline_helper); } + /* Simulate a call */ + /*Fix stack alignment*/ + x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x4); + /* This is the address the trampoline will return to */ + x86_push_reg (code, X86_EAX); + /* Dummy trampoline argument, since we call the generic trampoline directly */ + x86_push_imm (code, 0); + x86_jump_code (code, tramp); nacl_global_codeman_validate (&buf, tramp_size, &code); mono_arch_flush_icache (buf, code - buf); g_assert (code - buf <= tramp_size); - if (mono_jit_map_is_enabled ()) - mono_emit_jit_tramp (buf, code - buf, "handler_block_trampoline"); + if (info) + *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops); return buf; } @@ -1087,7 +1150,7 @@ guint8* mono_arch_get_call_target (guint8 *code) { if (code [-5] == 0xe8) { - guint32 disp = *(guint32*)(code - 4); + gint32 disp = *(gint32*)(code - 4); guint8 *target = code + disp; return target; @@ -1101,3 +1164,44 @@ mono_arch_get_plt_info_offset (guint8 *plt_entry, mgreg_t *regs, guint8 *code) { return *(guint32*)(plt_entry + NACL_SIZE (6, 12)); } + +/* + * mono_arch_get_gsharedvt_arg_trampoline: + * + * Return a trampoline which passes ARG to the gsharedvt in/out trampoline ADDR. + */ +gpointer +mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr) +{ + guint8 *code, *start; + int buf_len; + + buf_len = 10; + + start = code = mono_domain_code_reserve (domain, buf_len); + + x86_mov_reg_imm (code, X86_EAX, arg); + x86_jump_code (code, addr); + g_assert ((code - start) <= buf_len); + + nacl_domain_code_validate (domain, &start, buf_len, &code); + mono_arch_flush_icache (start, code - start); + + return start; +} + +#if defined(ENABLE_GSHAREDVT) + +#include "../../../mono-extensions/mono/mini/tramp-x86-gsharedvt.c" + +#else + +gpointer +mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) +{ + if (info) + *info = NULL; + return NULL; +} + +#endif /* !MONOTOUCH */