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