[runtime] Implement the new suspend infrastructure on windows.
[mono.git] / mono / mini / tramp-amd64.c
index f81bd33e48303205a5a9a2e3b035c859da3690ae..9ba8502250f72f86aaf5dd58682fef27ebbdf4c7 100644 (file)
@@ -13,6 +13,7 @@
 #include <config.h>
 #include <glib.h>
 
+#include <mono/metadata/abi-details.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
@@ -34,8 +35,6 @@
 
 #define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f))
 
-static guint8* nullified_class_init_trampoline;
-
 /*
  * mono_arch_get_unbox_trampoline:
  * @m: method pointer
@@ -165,11 +164,11 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
                                /* Print some diagnostics */
                                MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (char*)orig_code);
                                if (ji)
-                                       fprintf (stderr, "At %s, offset 0x%zx\n", mono_method_full_name (ji->method, TRUE), (guint8*)orig_code - (guint8*)ji->code_start);
+                                       fprintf (stderr, "At %s, offset 0x%zx\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (guint8*)orig_code - (guint8*)ji->code_start);
                                fprintf (stderr, "Addr: %p\n", addr);
                                ji = mono_jit_info_table_find (mono_domain_get (), (char*)addr);
                                if (ji)
-                                       fprintf (stderr, "Callee: %s\n", mono_method_full_name (ji->method, TRUE));
+                                       fprintf (stderr, "Callee: %s\n", mono_method_full_name (jinfo_get_method (ji), TRUE));
                                g_assert_not_reached ();
 #else
                                /* 
@@ -336,6 +335,7 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs)
        guint8 buf [16];
        MonoJitInfo *ji = NULL;
        gboolean can_write;
+       gpointer tramp = mini_get_nullified_class_init_trampoline ();
 
        if (mono_use_llvm) {
                /* code - 7 might be before the start of the method */
@@ -360,7 +360,7 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs)
                vtable_slot = get_vcall_slot_addr (code, regs);
                g_assert (vtable_slot);
 
-               *vtable_slot = nullified_class_init_trampoline;
+               *vtable_slot = tramp;
        } else if (buf [2] == 0xe8) {
                /* call <TARGET> */
                //guint8 *buf = code - 2;
@@ -378,11 +378,11 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs)
                buf [4] = 0x90;
                */
 
-               mono_arch_patch_callsite (code - 5, code, nullified_class_init_trampoline);
+               mono_arch_patch_callsite (code - 5, code, tramp);
        } else if ((buf [5] == 0xff) && x86_modrm_mod (buf [6]) == 3 && x86_modrm_reg (buf [6]) == 2) {
                /* call *<reg> */
                /* Generated by the LLVM JIT or on platforms without MAP_32BIT set */
-               mono_arch_patch_callsite (code - 13, code, nullified_class_init_trampoline);
+               mono_arch_patch_callsite (code - 13, code, tramp);
        } else if (buf [4] == 0x90 || buf [5] == 0xeb || buf [6] == 0x66) {
                /* Already changed by another thread */
                ;
@@ -393,15 +393,6 @@ 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);
-}
-
 static void
 stack_unaligned (MonoTrampolineType tramp_type)
 {
@@ -432,7 +423,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        code = buf = mono_global_codeman_reserve (kMaxCodeSize);
 
-       framesize = kMaxCodeSize + sizeof (MonoLMF);
+       framesize = kMaxCodeSize + sizeof (MonoLMFTramp);
        framesize = (framesize + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
 
        orig_rsp_to_rbp_offset = 0;
@@ -587,7 +578,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        /* Save LMF begin */
 
-       offset += sizeof (MonoLMF);
+       offset += sizeof (MonoLMFTramp);
        lmf_offset = - offset;
 
        /* Save ip */
@@ -595,31 +586,17 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
                amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, 8, sizeof(gpointer));
        else
                amd64_mov_reg_imm (code, AMD64_R11, 0);
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rip), AMD64_R11, sizeof(mgreg_t));
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rip), AMD64_R11, sizeof(mgreg_t));
        /* Save fp */
        amd64_mov_reg_membase (code, AMD64_R11, AMD64_RSP, framesize, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rbp), AMD64_R11, sizeof(mgreg_t));
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), AMD64_R11, sizeof(mgreg_t));
        /* Save sp */
        amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
        amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
-       /* Save method */
-       if (tramp_type == MONO_TRAMPOLINE_JIT || tramp_type == MONO_TRAMPOLINE_JUMP) {
-               amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, arg_offset, sizeof(gpointer));
-               amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), AMD64_R11, sizeof(gpointer));
-       } else {
-               amd64_mov_membase_imm (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), 0, sizeof(gpointer));
-       }
-       /* Save callee saved regs */
-#ifdef TARGET_WIN32
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rdi), AMD64_RDI, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsi), AMD64_RSI, sizeof(mgreg_t));
-#endif
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rbx), AMD64_RBX, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r12), AMD64_R12, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r13), AMD64_R13, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r14), AMD64_R14, sizeof(mgreg_t));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r15), AMD64_R15, sizeof(mgreg_t));
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
+       /* Save pointer to registers */
+       amd64_lea_membase (code, AMD64_R11, AMD64_RBP, saved_regs_offset);
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, regs), AMD64_R11, sizeof(mgreg_t));
 
        if (aot) {
                code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
@@ -629,12 +606,13 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        amd64_call_reg (code, AMD64_R11);
 
        /* Save lmf_addr */
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), AMD64_RAX, sizeof(gpointer));
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), AMD64_RAX, sizeof(gpointer));
        /* Save previous_lmf */
-       /* Set the lowest bit to 1 to signal that this LMF has the ip field set */
+       /* Set the lowest bit to signal that this LMF has the ip field set */
+       /* Set the third lowest bit to signal that this is a MonoLMFTramp structure */
        amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
-       amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 1, sizeof(gpointer));
-       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
+       amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 0x5, sizeof(gpointer));
+       amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
        /* Set new lmf */
        amd64_lea_membase (code, AMD64_R11, AMD64_RBP, lmf_offset);
        amd64_mov_membase_reg (code, AMD64_RAX, 0, AMD64_R11, sizeof(gpointer));
@@ -681,10 +659,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
        amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, res_offset, sizeof(mgreg_t));        
 
        /* Restore LMF */
-
-       amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
-       amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 1, sizeof(gpointer));
-       amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sizeof(gpointer));
+       amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
+       amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 0x5, sizeof(gpointer));
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + MONO_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), sizeof(gpointer));
        amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
 
        /* 
@@ -720,11 +697,6 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 
        mono_arch_flush_icache (buf, code - buf);
 
-       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);
@@ -750,9 +722,6 @@ mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info)
        if (info)
                *info = mono_tramp_info_create ("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");
-
        return buf;
 }
 
@@ -865,7 +834,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
                amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
        } else {
                /* load rgctx ptr from vtable */
-               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, G_STRUCT_OFFSET (MonoVTable, runtime_generic_context), sizeof(gpointer));
+               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), sizeof(gpointer));
                /* is the rgctx ptr null? */
                amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
                /* if yes, jump to actual trampoline */
@@ -1004,7 +973,7 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
 
        unwind_ops = mono_arch_get_cie_program ();
 
-       if (mono_thread_get_tls_offset () != -1) {
+       if (!aot && mono_thread_get_tls_offset () != -1) {
                /* MonoObject* obj is in RDI */
                /* is obj null? */
                amd64_test_reg_reg (code, AMD64_RDI, AMD64_RDI);
@@ -1013,7 +982,7 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
                amd64_branch8 (code, X86_CC_Z, -1, 1);
 
                /* load obj->synchronization to RCX */
-               amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, G_STRUCT_OFFSET (MonoObject, synchronisation), 8);
+               amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8);
 
                if (mono_gc_is_moving ()) {
                        /*if bit zero is set it's a thin hash*/
@@ -1035,7 +1004,7 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
                /* load MonoInternalThread* into RDX */
                code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ());
                /* load TID into RDX */
-               amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 8);
+               amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8);
 
                /* is synchronization->owner null? */
                amd64_alu_membase_imm_size (code, X86_CMP, AMD64_RCX, owner_offset, 0, 8);
@@ -1129,7 +1098,7 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
 
        unwind_ops = mono_arch_get_cie_program ();
 
-       if (mono_thread_get_tls_offset () != -1) {
+       if (!aot && mono_thread_get_tls_offset () != -1) {
                /* MonoObject* obj is in RDI */
                /* is obj null? */
                amd64_test_reg_reg (code, AMD64_RDI, AMD64_RDI);
@@ -1138,7 +1107,7 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
                amd64_branch8 (code, X86_CC_Z, -1, 1);
 
                /* load obj->synchronization to RCX */
-               amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, G_STRUCT_OFFSET (MonoObject, synchronisation), 8);
+               amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RDI, MONO_STRUCT_OFFSET (MonoObject, synchronisation), 8);
 
                if (mono_gc_is_moving ()) {
                        /*if bit zero is set it's a thin hash*/
@@ -1161,7 +1130,7 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
                /* load MonoInternalThread* into RDX */
                code = mono_amd64_emit_tls_get (code, AMD64_RDX, mono_thread_get_tls_offset ());
                /* load TID into RDX */
-               amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, G_STRUCT_OFFSET (MonoInternalThread, tid), 8);
+               amd64_mov_reg_membase (code, AMD64_RDX, AMD64_RDX, MONO_STRUCT_OFFSET (MonoInternalThread, tid), 8);
                /* is synchronization->owner == TID */
                amd64_alu_membase_reg_size (code, X86_CMP, AMD64_RCX, owner_offset, AMD64_RDX, 8);
                /* if no, jump to actual trampoline */
@@ -1242,11 +1211,16 @@ handler_block_trampoline_helper (gpointer *ptr)
 }
 
 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);
 
        /*
@@ -1255,7 +1229,7 @@ mono_arch_create_handler_block_trampoline (void)
 
        if (mono_get_jit_tls_offset () != -1) {
                code = mono_amd64_emit_tls_get (code, AMD64_RDI, mono_get_jit_tls_offset ());
-               amd64_mov_reg_membase (code, AMD64_RDI, AMD64_RDI, G_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8);
+               amd64_mov_reg_membase (code, AMD64_RDI, AMD64_RDI, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 8);
                /* Simulate a call */
                amd64_push_reg (code, AMD64_RAX);
                amd64_jump_code (code, tramp);
@@ -1270,8 +1244,8 @@ mono_arch_create_handler_block_trampoline (void)
        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;
 }
@@ -1285,7 +1259,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;