From 884f608c3fbe8b0178dd1c7d01ce4d92d3797a15 Mon Sep 17 00:00:00 2001 From: Paolo Molaro Date: Tue, 10 Jul 2007 15:23:02 +0000 Subject: [PATCH] Tue Jul 10 17:33:12 CEST 2007 Paolo Molaro * inssel.brg, mini.c, mini.h, mini-trampolines.c: arch-independent IMT JIT code from Massimiliano Mantione (massi@ximian.com) with small cleanups from me. svn path=/trunk/mono/; revision=81720 --- mono/mini/ChangeLog | 6 +++++ mono/mini/inssel.brg | 24 +++++++++++++++++ mono/mini/mini-trampolines.c | 51 +++++++++++++++++++++++++++++++++++- mono/mini/mini.c | 12 +++++++++ mono/mini/mini.h | 4 +++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 77858bd9705..daf1bb861b6 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,4 +1,10 @@ +Tue Jul 10 17:33:12 CEST 2007 Paolo Molaro + + * inssel.brg, mini.c, mini.h, mini-trampolines.c: + arch-independent IMT JIT code from Massimiliano + Mantione (massi@ximian.com) with small cleanups from me. + Tue Jul 10 13:07:24 CEST 2007 Paolo Molaro * Makefile.am: fix svn invocation to get the svn revision to be diff --git a/mono/mini/inssel.brg b/mono/mini/inssel.brg index bae7238947b..3ec201ed3a8 100644 --- a/mono/mini/inssel.brg +++ b/mono/mini/inssel.brg @@ -1719,6 +1719,23 @@ mini_emit_load_intf_bit_reg_vtable (MonoCompile *s, int intf_bit_reg, int vtable } } +#ifdef MONO_ARCH_HAVE_IMT +static void +emit_imt_argument (MonoCompile *cfg, MonoCallInst *call) { +#ifdef MONO_ARCH_IMT_REG + MonoInst *inst; + MONO_INST_NEW (cfg, inst, OP_PCONST); + inst->inst_p0 = call->method; + inst->dreg = mono_regstate_next_int (cfg->rs); + mono_bblock_add_inst (cfg->cbb, inst); + + mono_call_inst_add_outarg_reg (cfg, call, inst->dreg, MONO_ARCH_IMT_REG, FALSE); +#else + mono_arch_emit_imt_argument (cfg, call); +#endif +} +#endif + static void mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop) { @@ -1783,9 +1800,16 @@ mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop vtable_reg = mono_regstate_next_int (cfg->rs); MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable)); if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) { +#ifdef MONO_ARCH_HAVE_IMT + guint32 imt_slot = mono_method_get_imt_slot (method); + emit_imt_argument (cfg, (MonoCallInst*)tree); + slot_reg = vtable_reg; + tree->inst_offset = (imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P; +#else slot_reg = mono_regstate_next_int (cfg->rs); mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass); tree->inst_offset = method->slot * SIZEOF_VOID_P; +#endif } else { slot_reg = vtable_reg; tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (method->slot * SIZEOF_VOID_P); diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 4c2c03c3d0d..f0f1ebdaee4 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -13,6 +13,49 @@ #include "mini.h" +#ifdef MONO_ARCH_HAVE_IMT + +static gpointer* +mono_convert_imt_slot_to_vtable_slot (gpointer* slot, gpointer *regs, MonoMethod *method) { + MonoObject *this_argument = mono_arch_find_this_argument (regs, method); + MonoVTable *vt = this_argument->vtable; + int displacement = slot - ((gpointer*)vt); + + if (displacement > 0) { + /* slot is in the vtable, not in the IMT */ +#if DEBUG_IMT + printf ("mono_convert_imt_slot_to_vtable_slot: slot %p is in the vtable, not in the IMT\n", slot); +#endif + return slot; + } else { + MonoMethod *imt_method = mono_arch_find_imt_method (regs); + int interface_offset = mono_class_interface_offset (vt->klass, imt_method->klass); + int imt_slot = MONO_IMT_SIZE + displacement; + +#if DEBUG_IMT + printf ("mono_convert_imt_slot_to_vtable_slot: method = %s.%s.%s, imt_method = %s.%s.%s\n", + method->klass->name_space, method->klass->name, method->name, + imt_method->klass->name_space, imt_method->klass->name, imt_method->name); +#endif + g_assert (imt_slot < MONO_IMT_SIZE); + if (vt->imt_collisions_bitmap & (1 << imt_slot)) { + int vtable_offset = interface_offset + imt_method->slot; + gpointer *vtable_slot = & (vt->vtable [vtable_offset]); +#if DEBUG_IMT + printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, and colliding becomes %p[%d] (interface_offset = %d, method->slot = %d)\n", slot, imt_slot, vtable_slot, vtable_offset, interface_offset, imt_method->slot); +#endif + g_assert (vtable_offset >= 0); + return vtable_slot; + } else { +#if DEBUG_IMT + printf ("mono_convert_imt_slot_to_vtable_slot: slot %p[%d] is in the IMT, but not colliding\n", slot, imt_slot); +#endif + return slot; + } + } +} +#endif + /** * mono_magic_trampoline: * @@ -39,8 +82,12 @@ mono_magic_trampoline (gssize *regs, guint8 *code, MonoMethod *m, guint8* tramp) g_assert (*vtable_slot); - if (mono_aot_is_got_entry (code, (guint8*)vtable_slot) || mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot)) + 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); +#endif *vtable_slot = mono_get_addr_from_ftnptr (addr); + } } else { guint8 *plt_entry = mono_aot_get_plt_entry (code); @@ -250,3 +297,5 @@ mono_delegate_trampoline (gssize *regs, guint8 *code, MonoClass *klass, guint8* } #endif + + diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 34938f65a76..18610721170 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -11721,6 +11721,9 @@ mini_init (const char *filename, const char *runtime_version) mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); +#ifdef MONO_ARCH_HAVE_IMT + mono_install_imt_thunk_builder (mono_arch_build_imt_thunk); +#endif if (debug_options.collect_pagefault_stats) { mono_raw_buffer_set_make_unreadable (TRUE); mono_aot_set_make_unreadable (TRUE); @@ -11957,6 +11960,15 @@ print_jit_stats (void) g_print ("Dynamic code bytes: %ld\n", mono_stats.dynamic_code_bytes_count); g_print ("Dynamic code frees: %ld\n", mono_stats.dynamic_code_frees_count); + g_print ("IMT tables size: %ld\n", mono_stats.imt_tables_size); + g_print ("IMT number of tables: %ld\n", mono_stats.imt_number_of_tables); + g_print ("IMT number of methods: %ld\n", mono_stats.imt_number_of_methods); + g_print ("IMT used slots: %ld\n", mono_stats.imt_used_slots); + g_print ("IMT colliding slots: %ld\n", mono_stats.imt_slots_with_collisions); + g_print ("IMT max collisions: %ld\n", mono_stats.imt_max_collisions_in_slot); + g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions); + g_print ("IMT thunks size: %ld\n", mono_stats.imt_thunks_size); + if (mono_use_security_manager) { g_print ("\nDecl security check : %ld\n", mono_jit_stats.cas_declsec_check); g_print ("LinkDemand (user) : %ld\n", mono_jit_stats.cas_linkdemand); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index a8719be69da..6463f588253 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1012,6 +1012,10 @@ void mono_arch_patch_delegate_trampoline (guint8 *code, guint8 *tramp, gs gpointer mono_arch_get_this_arg_from_call (MonoMethodSignature *sig, gssize *regs, guint8 *code); 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; +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; /* Exception handling */ gboolean mono_handle_exception (MonoContext *ctx, gpointer obj, -- 2.25.1