+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
}
}
+#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)
{
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);
#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:
*
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);
}
#endif
+
+
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);
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);
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,