Author: zoltan
Date: 2007-07-11 16:02:26 -0400 (Wed, 11 Jul 2007)
New Revision: 81830

Modified:
   trunk/mono/mono/mini/ChangeLog
   trunk/mono/mono/mini/mini-amd64.c
   trunk/mono/mono/mini/mini-amd64.h
   trunk/mono/mono/mini/mini-trampolines.c
   trunk/mono/mono/mini/mini-x86.c
   trunk/mono/mono/mini/mini.h
Log:
2007-07-11  Zoltan Varga  <[EMAIL PROTECTED]>

        * mini-amd64.c (mono_arch_get_vcall_slot_addr): Handle signed 
displacements too.

        * mini.h mini-x86.h mini-trampolines.c: Change the signature of 
mono_arch_find_imt_method () to pass the calling code address too.

        * mini-amd64.c: Add preliminary IMT implementation.


Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog      2007-07-11 19:52:35 UTC (rev 81829)
+++ trunk/mono/mono/mini/ChangeLog      2007-07-11 20:02:26 UTC (rev 81830)
@@ -1,4 +1,11 @@
+2007-07-11  Zoltan Varga  <[EMAIL PROTECTED]>
 
+       * mini-amd64.c (mono_arch_get_vcall_slot_addr): Handle signed 
displacements too.
+
+       * mini.h mini-x86.h mini-trampolines.c: Change the signature of 
mono_arch_find_imt_method () to pass the calling code address too.
+
+       * mini-amd64.c: Add preliminary IMT implementation.
+       
 Wed Jul 11 18:21:30 CEST 2007 Paolo Molaro <[EMAIL PROTECTED]>
 
        * mini-x86.c: adjusted mono_arch_get_vcall_slot_addr () to

Modified: trunk/mono/mono/mini/mini-amd64.c
===================================================================
--- trunk/mono/mono/mini/mini-amd64.c   2007-07-11 19:52:35 UTC (rev 81829)
+++ trunk/mono/mono/mini/mini-amd64.c   2007-07-11 20:02:26 UTC (rev 81830)
@@ -5158,7 +5158,7 @@
 mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs)
 {
        guint32 reg;
-       guint32 disp;
+       gint32 disp;
        guint8 rex = 0;
 
        /* go to the start of the call instruction
@@ -5196,7 +5196,7 @@
                if (IS_REX (code [0]))
                        rex = code [0];
                reg = amd64_modrm_rm (code [2]);
-               disp = *(guint32*)(code + 3);
+               disp = *(gint32*)(code + 3);
                //printf ("B: [%%r%d+0x%x]\n", reg, disp);
        }
        else if (code [2] == 0xe8) {
@@ -5212,7 +5212,7 @@
                if (IS_REX (code [3]))
                        rex = code [3];
                reg = amd64_modrm_rm (code [5]);
-               disp = *(guint8*)(code + 6);
+               disp = *(gint8*)(code + 6);
                //printf ("B: [%%r%d+0x%x]\n", reg, disp);
        }
        else if ((code [5] == 0xff) && (amd64_modrm_reg (code [6]) == 0x2) && 
(amd64_modrm_mod (code [6]) == 0x0)) {
@@ -5367,6 +5367,122 @@
        }
 }
 
+#ifdef MONO_ARCH_HAVE_IMT
+
+#define IMT_THUNK_SIZE 32
+
+/*
+ * LOCKING: called with the domain lock held
+ */
+gpointer
+mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, 
MonoIMTCheckItem **imt_entries, int count)
+{
+       int i;
+       int size = 0;
+       guint8 *code, *start, *mempool_start;
+
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               if (!item->is_equals) {
+                       imt_entries [item->check_target_idx]->compare_done = 
TRUE;
+               }
+       }
+       //code = mono_code_manager_reserve (domain->code_mp, size);
+       size = count * IMT_THUNK_SIZE;
+       code = g_malloc (size);
+       start = code;
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               item->code_target = code;
+               g_assert (amd64_is_imm32 (item->method));
+               if (item->is_equals) {
+                       if (item->check_target_idx) {
+                               if (!item->compare_done)
+                                       amd64_alu_reg_imm (code, X86_CMP, 
MONO_ARCH_IMT_REG, (guint32)(gssize)item->method);
+                               item->jmp_code = code;
+                               amd64_branch8 (code, X86_CC_NE, 0, FALSE);
+                               amd64_mov_reg_imm (code, AMD64_R11, & 
(vtable->vtable [item->vtable_slot]));
+                               amd64_jump_membase (code, AMD64_R11, 0);
+                       } else {
+                               /* enable the commented code to assert on wrong 
method */
+#if 0
+                               amd64_alu_reg_imm (code, X86_CMP, 
MONO_ARCH_IMT_REG, (guint32)(gssize)item->method);
+                               item->jmp_code = code;
+                               amd64_branch8 (code, X86_CC_NE, 0, FALSE);
+                               amd64_mov_reg_imm (code, AMD64_R11, & 
(vtable->vtable [item->vtable_slot]));
+                               amd64_jump_membase (code, AMD64_R11, 0);
+                               amd64_patch (item->jmp_code, code);
+                               amd64_breakpoint (code);
+                               item->jmp_code = NULL;
+#else
+                               amd64_mov_reg_imm (code, AMD64_R11, & 
(vtable->vtable [item->vtable_slot]));
+                               amd64_jump_membase (code, AMD64_R11, 0);
+#endif
+                       }
+               } else {
+                       amd64_alu_reg_imm (code, X86_CMP, MONO_ARCH_IMT_REG, 
(guint32)(gssize)item->method);
+                       item->jmp_code = code;
+                       if (x86_is_imm8 ((item->check_target_idx - i) * 
IMT_THUNK_SIZE))
+                               amd64_branch8 (code, X86_CC_GE, 0, FALSE);
+                       else
+                               amd64_branch32 (code, X86_CC_GE, 0, FALSE);
+               }
+               item->chunk_size = code - item->code_target;
+       }
+       /* patch the branches to get to the target items */
+       for (i = 0; i < count; ++i) {
+               MonoIMTCheckItem *item = imt_entries [i];
+               if (item->jmp_code) {
+                       if (item->check_target_idx) {
+                               amd64_patch (item->jmp_code, imt_entries 
[item->check_target_idx]->code_target);
+                       }
+               }
+       }
+               
+       mono_stats.imt_thunks_size += code - start;
+       g_assert (code - start <= size);
+
+       mempool_start = mono_code_manager_reserve (domain->code_mp, code - 
start);
+       memcpy (mempool_start, start, code - start);
+
+       return mempool_start;
+}
+
+MonoMethod*
+mono_arch_find_imt_method (gpointer *regs, guint8 *code)
+{
+       /* 
+        * R11 is clobbered by the trampoline code, so we have to retrieve the 
method from the
+        * code.
+        * 41 bb c0 f7 89 00     mov    $0x89f7c0,%r11d
+        * ff 90 68 ff ff ff     callq  *0xffffffffffffff68(%rax)
+        */
+       /* Similar to get_vcall_slot_addr () */
+
+       /* Find the start of the call instruction */
+       code -= 7;
+       if ((code [1] == 0xff) && (amd64_modrm_reg (code [2]) == 0x2) && 
(amd64_modrm_mod (code [2]) == 0x2)) {
+               /* call *[reg+disp32] */
+               code += 1;
+       } else if ((code [4] == 0xff) && (amd64_modrm_reg (code [5]) == 0x2) && 
(amd64_modrm_mod (code [5]) == 0x1)) {
+               /* call *[reg+disp8] */
+               code += 4;
+       } else
+               g_assert_not_reached ();
+
+       /* Find the start of the mov instruction */
+       code -= 6;
+       g_assert (code [0] == 0x41 && code [1] == 0xbb);
+       return (MonoMethod*)(gssize)*(guint32*)(code + 2);
+}
+
+MonoObject*
+mono_arch_find_this_argument (gpointer *regs, MonoMethod *method)
+{
+       return mono_arch_get_this_arg_from_call (mono_method_signature 
(method), (gssize*)regs, NULL);
+}
+#endif
+
 MonoInst*
 mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, 
MonoMethodSignature *fsig, MonoInst **args)
 {

Modified: trunk/mono/mono/mini/mini-amd64.h
===================================================================
--- trunk/mono/mono/mini/mini-amd64.h   2007-07-11 19:52:35 UTC (rev 81829)
+++ trunk/mono/mono/mini/mini-amd64.h   2007-07-11 20:02:26 UTC (rev 81830)
@@ -255,6 +255,8 @@
 #define MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_CREATE_VARS 1
+/* #define MONO_ARCH_HAVE_IMT 1 */
+#define MONO_ARCH_IMT_REG AMD64_R11
 
 gboolean
 mono_amd64_is_sse2 (void);

Modified: trunk/mono/mono/mini/mini-trampolines.c
===================================================================
--- trunk/mono/mono/mini/mini-trampolines.c     2007-07-11 19:52:35 UTC (rev 
81829)
+++ trunk/mono/mono/mini/mini-trampolines.c     2007-07-11 20:02:26 UTC (rev 
81830)
@@ -16,7 +16,8 @@
 #ifdef MONO_ARCH_HAVE_IMT
 
 static gpointer*
-mono_convert_imt_slot_to_vtable_slot (gpointer* slot, gpointer *regs, 
MonoMethod *method) {
+mono_convert_imt_slot_to_vtable_slot (gpointer* slot, gpointer *regs, guint8 
*code, MonoMethod *method)
+{
        MonoObject *this_argument = mono_arch_find_this_argument (regs, method);
        MonoVTable *vt = this_argument->vtable;
        int displacement = slot - ((gpointer*)vt);
@@ -28,7 +29,7 @@
 #endif
                return slot;
        } else {
-               MonoMethod *imt_method = mono_arch_find_imt_method (regs);
+               MonoMethod *imt_method = mono_arch_find_imt_method (regs, code);
                int interface_offset = mono_class_interface_offset (vt->klass, 
imt_method->klass);
                int imt_slot = MONO_IMT_SIZE + displacement;
 
@@ -84,7 +85,7 @@
 
                if (mono_aot_is_got_entry (code, (guint8*)vtable_slot) || 
mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) {
 #ifdef MONO_ARCH_HAVE_IMT
-                       vtable_slot = mono_convert_imt_slot_to_vtable_slot 
(vtable_slot, (gpointer*)regs, m);
+                       vtable_slot = mono_convert_imt_slot_to_vtable_slot 
(vtable_slot, (gpointer*)regs, code, m);
 #endif
                        *vtable_slot = mono_get_addr_from_ftnptr (addr);
                }
@@ -177,7 +178,7 @@
 #ifdef MONO_ARCH_HAVE_IMT
                if (!method)
                        method = mono_get_method (image, token, NULL);
-               vtable_slot = mono_convert_imt_slot_to_vtable_slot 
(vtable_slot, (gpointer*)regs, method);
+               vtable_slot = mono_convert_imt_slot_to_vtable_slot 
(vtable_slot, (gpointer*)regs, code, method);
 #endif
                *vtable_slot = addr;
        }

Modified: trunk/mono/mono/mini/mini-x86.c
===================================================================
--- trunk/mono/mono/mini/mini-x86.c     2007-07-11 19:52:35 UTC (rev 81829)
+++ trunk/mono/mono/mini/mini-x86.c     2007-07-11 20:02:26 UTC (rev 81830)
@@ -4203,12 +4203,14 @@
 }
 
 MonoMethod*
-mono_arch_find_imt_method (gpointer *regs) {
+mono_arch_find_imt_method (gpointer *regs, guint8 *code)
+{
        return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
 }
 
 MonoObject*
-mono_arch_find_this_argument (gpointer *regs, MonoMethod *method) {
+mono_arch_find_this_argument (gpointer *regs, MonoMethod *method)
+{
        MonoMethodSignature *sig = mono_method_signature (method);
        CallInfo *cinfo = get_call_info (NULL, sig, FALSE);
        int this_argument_offset;

Modified: trunk/mono/mono/mini/mini.h
===================================================================
--- trunk/mono/mono/mini/mini.h 2007-07-11 19:52:35 UTC (rev 81829)
+++ trunk/mono/mono/mini/mini.h 2007-07-11 20:02:26 UTC (rev 81830)
@@ -1013,7 +1013,7 @@
 gpointer mono_arch_get_delegate_invoke_impl     (MonoMethodSignature *sig, 
gboolean has_target);
 gpointer mono_arch_create_specific_trampoline   (gpointer arg1, 
MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) 
MONO_INTERNAL;
 void        mono_arch_emit_imt_argument         (MonoCompile *cfg, 
MonoCallInst *call) MONO_INTERNAL;
-MonoMethod* mono_arch_find_imt_method           (gpointer *regs) MONO_INTERNAL;
+MonoMethod* mono_arch_find_imt_method           (gpointer *regs, guint8 *code) 
MONO_INTERNAL;
 MonoObject* mono_arch_find_this_argument        (gpointer *regs, MonoMethod 
*method) MONO_INTERNAL;
 gpointer    mono_arch_build_imt_thunk           (MonoVTable *vtable, 
MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count) MONO_INTERNAL;
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to