X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-amd64-gsharedvt.c;h=17a6849ed2564315e2f81d0b93601fcac42e779f;hb=04cbe795fa9ff9e3ce50402857053a0a599e9457;hp=1be75933c8efa6041ac798234d72967e4c8f6b8d;hpb=1639e26a6b22a59d0bfb8ad564530eeff593e4a3;p=mono.git diff --git a/mono/mini/tramp-amd64-gsharedvt.c b/mono/mini/tramp-amd64-gsharedvt.c index 1be75933c8e..17a6849ed25 100644 --- a/mono/mini/tramp-amd64-gsharedvt.c +++ b/mono/mini/tramp-amd64-gsharedvt.c @@ -1,10 +1,12 @@ -/* - * tramp-amd64-gsharedvt.c: libcorkscrew-based native unwinder +/** + * \file + * libcorkscrew-based native unwinder * * Authors: * Zoltan Varga * Rodrigo Kumpera * Andi McClure + * Johan Lorensson * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. @@ -16,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -89,6 +90,28 @@ mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpoi DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- [%d] (%d words) (%p) <- (%p)\n", dest_reg, source_reg, slot_count, &callee [dest_reg], &caller [source_reg]); break; } + case GSHAREDVT_ARG_BYREF_TO_BYVAL_U1: { + guint8 *addr = caller [source_reg]; + + callee [dest_reg] = (gpointer)(mgreg_t)*addr; + DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- (u1) [%d] (%p) <- (%p)\n", dest_reg, source_reg, &callee [dest_reg], &caller [source_reg]); + break; + } + case GSHAREDVT_ARG_BYREF_TO_BYVAL_U2: { + guint16 *addr = caller [source_reg]; + + callee [dest_reg] = (gpointer)(mgreg_t)*addr; + DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- (u2) [%d] (%p) <- (%p)\n", dest_reg, source_reg, &callee [dest_reg], &caller [source_reg]); + break; + } + case GSHAREDVT_ARG_BYREF_TO_BYVAL_U4: { + guint32 *addr = caller [source_reg]; + + callee [dest_reg] = (gpointer)(mgreg_t)*addr; + DEBUG_AMD64_GSHAREDVT_PRINT ("[%d] <- (u4) [%d] (%p) <- (%p)\n", dest_reg, source_reg, &callee [dest_reg], &caller [source_reg]); + break; + } + default: g_error ("cant handle arg marshal %d\n", arg_marshal); } @@ -138,15 +161,14 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint amd64_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); - mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL); + MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL)); + + mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain); - g_assert (0); return start; } - gpointer mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) { @@ -162,7 +184,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) int reg_area_size; buf_len = 2048; - buf = code = mono_global_codeman_reserve (buf_len); + buf = code = mono_global_codeman_reserve (buf_len + MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE); /* * We are being called by an gsharedvt arg trampoline, the info argument is in AMD64_RAX. @@ -208,6 +230,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) /* unwind markers 3/3 */ mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, AMD64_RBP); + mono_add_unwind_op_fp_alloc (unwind_ops, code, buf, AMD64_RBP, 0); /* setup the frame */ amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize); @@ -246,8 +269,8 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) - - + + */ /* Call start_gsharedvt_call () */ @@ -264,9 +287,25 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_start_gsharedvt_call"); - amd64_call_reg (code, AMD64_R11); + #ifdef TARGET_WIN32 + /* Since we are doing a call as part of setting up stackframe, the reserved shadow stack used by Windows platform is allocated up in + the callee stack area but currently the callee reg area is in between. Windows calling convention dictates that room is made on stack where + callee can save any parameters passed in registers. Since Windows x64 calling convention + uses 4 registers for the first 4 parameters, stack needs to be adjusted before making the call. + NOTE, Windows calling convention assumes that space for all registers have been reserved, regardless + of the number of function parameters actually used. + */ + int shadow_reg_size = 0; + + shadow_reg_size = ALIGN_TO (PARAM_REGS * sizeof(gpointer), MONO_ARCH_FRAME_ALIGNMENT); + amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, shadow_reg_size); + amd64_call_reg (code, AMD64_R11); + amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, shadow_reg_size); + #else + amd64_call_reg (code, AMD64_R11); + #endif } else { - g_error ("no aot"); + amd64_call_code (code, mono_amd64_start_gsharedvt_call); } /* Method to call is now on RAX. Restore regs and jump */ @@ -303,13 +342,14 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) */ /* Load vret_slot */ - amd64_mov_reg_membase (code, AMD64_RDI, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4); - amd64_alu_reg_imm (code, X86_SUB, AMD64_RDI, n_arg_regs + n_arg_fregs); - amd64_shift_reg_imm (code, X86_SHL, AMD64_RDI, 3); + /* Use first input parameter register as scratch since it is volatile on all platforms */ + amd64_mov_reg_membase (code, MONO_AMD64_ARG_REG1, AMD64_R10, MONO_STRUCT_OFFSET (GSharedVtCallInfo, vret_slot), 4); + amd64_alu_reg_imm (code, X86_SUB, MONO_AMD64_ARG_REG1, n_arg_regs + n_arg_fregs); + amd64_shift_reg_imm (code, X86_SHL, MONO_AMD64_ARG_REG1, 3); /* vret address is RBP - (framesize - caller_reg_area_offset) */ amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t)); - amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, AMD64_RDI); + amd64_alu_reg_reg (code, X86_ADD, AMD64_R11, MONO_AMD64_ARG_REG1); /* Load ret marshal type */ /* Load vret address in R11 */ @@ -367,10 +407,10 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) /* Address to write return to is in the original value of the register specified by vret_arg_reg. - This will be either RSI or RDI depending on whether this is a static call. + This will be either RSI, RDI (System V) or RCX, RDX (Windows) depending on whether this is a static call. Its location: We alloc 'framesize' bytes below RBP to save regs, info and rgctx. RSP = RBP - framesize - We store rdi at RSP + caller_reg_area_offset + slot_index_of (register) * 8. + We store RDI (System V), RCX (Windows) at RSP + caller_reg_area_offset + slot_index_of (register) * 8. address: RBP - framesize + caller_reg_area_offset + 8*slot */ @@ -427,10 +467,17 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) mono_amd64_patch (br_ret [i], code); /* Exit code path */ +#if TARGET_WIN32 + amd64_lea_membase (code, AMD64_RSP, AMD64_RBP, 0); + amd64_pop_reg (code, AMD64_RBP); + mono_add_unwind_op_same_value (unwind_ops, code, buf, AMD64_RBP); +#else amd64_leave (code); +#endif amd64_ret (code); g_assert ((code - buf) < buf_len); + g_assert_checked (mono_arch_unwindinfo_validate_size (unwind_ops, MONO_MAX_TRAMPOLINE_UNWINDINFO_SIZE)); if (info) *info = mono_tramp_info_create ("gsharedvt_trampoline", buf, code - buf, ji, unwind_ops); @@ -439,6 +486,22 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) return buf; } +#else + +gpointer +mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr) +{ + g_assert_not_reached (); + return NULL; +} + +gpointer +mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) +{ + g_assert_not_reached (); + return NULL; +} + #endif #else @@ -450,4 +513,4 @@ mono_amd64_start_gsharedvt_call (GSharedVtCallInfo *info, gpointer *caller, gpoi return NULL; } -#endif \ No newline at end of file +#endif