[jit] Fix OP_GENERIC_CLASS_INIT on amd64 so it doesn't clobber the first arg register.
authorZoltan Varga <vargaz@gmail.com>
Sat, 16 May 2015 07:58:05 +0000 (09:58 +0200)
committerZoltan Varga <vargaz@gmail.com>
Sat, 16 May 2015 07:58:05 +0000 (09:58 +0200)
mono/mini/cpu-amd64.md
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h

index 7e6133abf42d5b4d40673cdcac36d24c2148e82e..a272a7e88e66badecc755e895df67c6131eb52bd 100755 (executable)
 #      b  base register (used in address references)
 #      f  floating point register
 #      a  EAX register
-#   d  EDX register
+#  d  EDX register
 #      l  long reg (forced eax:edx)
-#   s  ECX register
-#   c  register which can be used as a byte register (RAX..RDX)
+#  s  ECX register
+#  c  register which can be used as a byte register (RAX..RDX)
+#  A - first arg reg (rdi/rcx)
 #
 # len:number         describe the maximun length in bytes of the instruction
 #                   number is a positive integer.  If the length is not specified
@@ -796,4 +797,4 @@ gc_liveness_use: len:0
 gc_spill_slot_liveness_def: len:0
 gc_param_slot_liveness_def: len:0
 
-generic_class_init: src1:i len:32
+generic_class_init: src1:A len:32
index eaa569450e5dc619016ebba223dbc3ffcb5521ff..32dd3fed2c4af486756becf47d53bec5a238e216 100644 (file)
@@ -3626,7 +3626,6 @@ static void
 emit_generic_class_init (MonoCompile *cfg, MonoClass *klass)
 {
        MonoInst *vtable_arg;
-       MonoCallInst *call;
        int context_used;
 
        context_used = mini_class_check_context_used (cfg, klass);
@@ -3645,6 +3644,10 @@ emit_generic_class_init (MonoCompile *cfg, MonoClass *klass)
 #ifdef MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT
        MonoInst *ins;
 
+       /*
+        * Using an opcode instead of emitting IR here allows the hiding of the call inside the opcode,
+        * so this doesn't have to clobber any regs.
+        */
        /*
         * For LLVM, this requires that the code in the generic trampoline obtain the vtable argument according to
         * the normal calling convention of the platform.
@@ -3653,6 +3656,8 @@ emit_generic_class_init (MonoCompile *cfg, MonoClass *klass)
        ins->sreg1 = vtable_arg->dreg;
        MONO_ADD_INS (cfg->cbb, ins);
 #else
+       MonoCallInst *call;
+
        if (COMPILE_LLVM (cfg))
                call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_GENERIC_CLASS_INIT, NULL, helper_sig_generic_class_init_trampoline_llvm, &vtable_arg);
        else
index 958e19e9293a0233d39f1721ae5021ef096c518c..6b4949170d60e39e13c618a5499ebc2e60bbccf7 100644 (file)
@@ -4836,6 +4836,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        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);
 
@@ -4843,8 +4845,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        jump = code;
                        amd64_branch8 (code, X86_CC_NZ, -1, 1);
 
-                       if (ins->sreg1 != MONO_AMD64_ARG_REG1)
-                               amd64_mov_reg_reg (code, MONO_AMD64_ARG_REG1, ins->sreg1, 8);
                        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;
index 1859db4a35324db1de6e2a5c57bb35eaba648285..bd2885424b8a338861f2619dcd785aa37de39600 100644 (file)
@@ -147,7 +147,7 @@ struct sigcontext {
 #define MONO_ARCH_USE_FPSTACK FALSE
 #define MONO_ARCH_FPSTACK_SIZE 0
 
-#define MONO_ARCH_INST_FIXED_REG(desc) ((desc == '\0') ? -1 : ((desc == 'i' ? -1 : ((desc == 'a') ? AMD64_RAX : ((desc == 's') ? AMD64_RCX : ((desc == 'd') ? AMD64_RDX : -1))))))
+#define MONO_ARCH_INST_FIXED_REG(desc) ((desc == '\0') ? -1 : ((desc == 'i' ? -1 : ((desc == 'a') ? AMD64_RAX : ((desc == 's') ? AMD64_RCX : ((desc == 'd') ? AMD64_RDX : ((desc == 'A') ? MONO_AMD64_ARG_REG1 : -1)))))))
 
 /* RDX is clobbered by the opcode implementation before accessing sreg2 */
 #define MONO_ARCH_INST_SREG2_MASK(ins) (((ins [MONO_INST_CLOB] == 'a') || (ins [MONO_INST_CLOB] == 'd')) ? (1 << AMD64_RDX) : 0)