Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
		}
	}
}