static guint32 get_type_idx (MonoProfiler *p, MonoClass* klass) { guint32 idx_plus_one; if (!(idx_plus_one = GPOINTER_TO_UINT (g_hash_table_lookup (p->klass_to_table_idx, klass)))) { char* name = mono_type_get_name_full (mono_class_get_type (klass)); g_ptr_array_add (p->klass_table, name); idx_plus_one = p->klass_table->len; g_hash_table_insert (p->klass_to_table_idx, klass, idx_plus_one); if (idx_plus_one > p->type_live_data_size) resize_array (p->type_live_data, p->type_live_data_size, MAX (p->type_live_data_size << 1, idx_plus_one)); } return idx_plus_one - 1; }
mono_convert_imt_slot_to_vtable_slot (gpointer* slot, mgreg_t *regs, guint8 *code, MonoMethod *method, MonoMethod **impl_method, gboolean *need_rgctx_tramp, gboolean *variance_used, gpointer *aot_addr) { MonoObject *this_argument = mono_arch_get_this_arg_from_call (regs, code); 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, code); MonoMethod *impl; int interface_offset; int imt_slot = MONO_IMT_SIZE + displacement; /*This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement*/ interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, variance_used); if (interface_offset < 0) { g_error ("%s doesn't implement interface %s\n", mono_type_get_name_full (&vt->klass->byval_arg, 0), mono_type_get_name_full (&imt_method->klass->byval_arg, 0)); } mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method)); if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) { MonoGenericContext context = { NULL, NULL }; /* * Generic virtual method, imt_method contains the inflated interface * method, need to get the inflated impl method. */ /* imt_method->slot might not be set */ impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_declaring_generic_method (imt_method)->slot); if (impl->klass->generic_class) context.class_inst = impl->klass->generic_class->context.class_inst; context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst; impl = mono_class_inflate_generic_method (impl, &context); } else { /* Avoid loading metadata or creating a generic vtable if possible */ if (!vt->klass->valuetype) *aot_addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method)); else *aot_addr = NULL; if (*aot_addr) impl = NULL; else impl = mono_class_get_vtable_entry (vt->klass, interface_offset + mono_method_get_vtable_slot (imt_method)); } if (impl && mono_method_needs_static_rgctx_invoke (impl, FALSE)) *need_rgctx_tramp = TRUE; if (impl && impl->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) { WrapperInfo *info = mono_marshal_get_wrapper_info (impl); if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) { // FIXME: This needs a gsharedvt-out trampoline, since the caller uses the gsharedvt calling conv, but the // wrapper is a normal non-generic method. *need_rgctx_tramp = TRUE; //g_assert_not_reached (); } } *impl_method = impl; #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 slot = mono_method_get_vtable_index (imt_method); int vtable_offset; gpointer *vtable_slot; g_assert (slot != -1); vtable_offset = interface_offset + slot; 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 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; } } }