Tue Jul 10 17:33:12 CEST 2007 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Tue, 10 Jul 2007 15:23:02 +0000 (15:23 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Tue, 10 Jul 2007 15:23:02 +0000 (15:23 -0000)
* 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
mono/mini/inssel.brg
mono/mini/mini-trampolines.c
mono/mini/mini.c
mono/mini/mini.h

index 77858bd9705999505c7863bd7b12e2eea95dcf44..daf1bb861b68008cf6d4915e8fb4919f831917a8 100644 (file)
@@ -1,4 +1,10 @@
 
+Tue Jul 10 17:33:12 CEST 2007 Paolo Molaro <lupus@ximian.com>
+
+       * 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 <lupus@ximian.com>
 
        * Makefile.am: fix svn invocation to get the svn revision to be
index bae7238947bde6ce367cd4723bd1d5784031c959..3ec201ed3a810f095cdda9d6ae0981327afa3090 100644 (file)
@@ -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);
index 4c2c03c3d0d0c7e9431450ac8224e163105f04ca..f0f1ebdaee44782851e239bc37d6b89b4eabf621 100644 (file)
 
 #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
+
+
index 34938f65a76b76cdf02cae8199137303c30fda1c..1861072117003b2e0fea7235c72da57833b75ba8 100644 (file)
@@ -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);
index a8719be69da31bb2e5298a28a3a09079016bf198..6463f58825379e1ad3d5b66704fd868cca1d3d66 100644 (file)
@@ -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,