Merge pull request #1804 from esdrubal/processmodule
[mono.git] / mono / mini / mini-amd64.c
index 6dec1e35442eac4276b04a8817929fe6a3151448..744b42be16f8e8ebc3785dc684a64d5a2f980376 100644 (file)
@@ -4831,6 +4831,28 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        amd64_pop_reg (code, AMD64_RDI);
                        break;
                }
+               case OP_GENERIC_CLASS_INIT: {
+                       static int byte_offset = -1;
+                       static guint8 bitmask;
+                       guint8 *jump;
+
+                       g_assert (ins->sreg1 == MONO_AMD64_ARG_REG1);
+
+                       if (byte_offset < 0)
+                               mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+
+                       amd64_test_membase_imm_size (code, ins->sreg1, byte_offset, bitmask, 1);
+                       jump = code;
+                       amd64_branch8 (code, X86_CC_NZ, -1, 1);
+
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_generic_class_init", FALSE);
+                       ins->flags |= MONO_INST_GC_CALLSITE;
+                       ins->backend.pc_offset = code - cfg->native_code;
+
+                       x86_patch (jump, code);
+                       break;
+               }
+
                case OP_X86_LEA:
                        amd64_lea_memindex (code, ins->dreg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->backend.shift_amount);
                        break;
@@ -7660,7 +7682,7 @@ mono_arch_is_int_overflow (void *sigctx, void *info)
 
        mono_sigctx_to_monoctx (sigctx, &ctx);
 
-       rip = (guint8*)ctx.rip;
+       rip = (guint8*)ctx.gregs [AMD64_RIP];
 
        if (IS_REX (rip [0])) {
                reg = amd64_rex_b (rip [0]);
@@ -7673,47 +7695,7 @@ mono_arch_is_int_overflow (void *sigctx, void *info)
                /* idiv REG */
                reg += x86_modrm_rm (rip [1]);
 
-               switch (reg) {
-               case AMD64_RAX:
-                       value = ctx.rax;
-                       break;
-               case AMD64_RBX:
-                       value = ctx.rbx;
-                       break;
-               case AMD64_RCX:
-                       value = ctx.rcx;
-                       break;
-               case AMD64_RDX:
-                       value = ctx.rdx;
-                       break;
-               case AMD64_RBP:
-                       value = ctx.rbp;
-                       break;
-               case AMD64_RSP:
-                       value = ctx.rsp;
-                       break;
-               case AMD64_RSI:
-                       value = ctx.rsi;
-                       break;
-               case AMD64_RDI:
-                       value = ctx.rdi;
-                       break;
-               case AMD64_R12:
-                       value = ctx.r12;
-                       break;
-               case AMD64_R13:
-                       value = ctx.r13;
-                       break;
-               case AMD64_R14:
-                       value = ctx.r14;
-                       break;
-               case AMD64_R15:
-                       value = ctx.r15;
-                       break;
-               default:
-                       g_assert_not_reached ();
-                       reg = -1;
-               }                       
+               value = ctx.gregs [reg];
 
                if (value == -1)
                        return TRUE;
@@ -7869,6 +7851,39 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
        return start;
 }
 
+#define MAX_VIRTUAL_DELEGATE_OFFSET 32
+
+static gpointer
+get_delegate_virtual_invoke_impl (gboolean load_imt_reg, int offset, guint32 *code_len)
+{
+       guint8 *code, *start;
+       int size = 20;
+
+       if (offset / sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
+               return NULL;
+
+       start = code = mono_global_codeman_reserve (size);
+
+       /* Replace the this argument with the target */
+       amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
+       amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 8);
+
+       if (load_imt_reg) {
+               /* Load the IMT reg */
+               amd64_mov_reg_membase (code, MONO_ARCH_IMT_REG, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, method), 8);
+       }
+
+       /* Load the vtable */
+       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
+       amd64_jump_membase (code, AMD64_RAX, offset);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
+
+       if (code_len)
+               *code_len = code - start;
+
+       return start;
+}
+
 /*
  * mono_arch_get_delegate_invoke_impls:
  *
@@ -7894,6 +7909,18 @@ mono_arch_get_delegate_invoke_impls (void)
                g_free (tramp_name);
        }
 
+       for (i = 0; i < MAX_VIRTUAL_DELEGATE_OFFSET; ++i) {
+               code = get_delegate_virtual_invoke_impl (TRUE, i * SIZEOF_VOID_P, &code_len);
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", i);
+               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+               g_free (tramp_name);
+
+               code = get_delegate_virtual_invoke_impl (FALSE, i * SIZEOF_VOID_P, &code_len);
+               tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", i);
+               res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL));
+               g_free (tramp_name);
+       }
+
        return res;
 }
 
@@ -7955,26 +7982,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 gpointer
 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
 {
-       guint8 *code, *start;
-       int size = 20;
-
-       start = code = mono_global_codeman_reserve (size);
-
-       /* Replace the this argument with the target */
-       amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
-       amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 8);
-
-       if (load_imt_reg) {
-               /* Load the IMT reg */
-               amd64_mov_reg_membase (code, MONO_ARCH_IMT_REG, AMD64_RAX, MONO_STRUCT_OFFSET (MonoDelegate, method), 8);
-       }
-
-       /* Load the vtable */
-       amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, MONO_STRUCT_OFFSET (MonoObject, vtable), 8);
-       amd64_jump_membase (code, AMD64_RAX, offset);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
-
-       return start;
+       return get_delegate_virtual_invoke_impl (load_imt_reg, offset, NULL);
 }
 
 void
@@ -8290,44 +8298,16 @@ mono_arch_print_tree (MonoInst *tree, int arity)
        return 0;
 }
 
-#define _CTX_REG(ctx,fld,i) ((&ctx->fld)[i])
-
 mgreg_t
 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
 {
-       switch (reg) {
-       case AMD64_RCX: return ctx->rcx;
-       case AMD64_RDX: return ctx->rdx;
-       case AMD64_RBX: return ctx->rbx;
-       case AMD64_RBP: return ctx->rbp;
-       case AMD64_RSP: return ctx->rsp;
-       default:
-               return _CTX_REG (ctx, rax, reg);
-       }
+       return ctx->gregs [reg];
 }
 
 void
 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
 {
-       switch (reg) {
-       case AMD64_RCX:
-               ctx->rcx = val;
-               break;
-       case AMD64_RDX: 
-               ctx->rdx = val;
-               break;
-       case AMD64_RBX:
-               ctx->rbx = val;
-               break;
-       case AMD64_RBP:
-               ctx->rbp = val;
-               break;
-       case AMD64_RSP:
-               ctx->rsp = val;
-               break;
-       default:
-               _CTX_REG (ctx, rax, reg) = val;
-       }
+       ctx->gregs [reg] = val;
 }
 
 gpointer