提交 742deba4 编写于 作者: R Rodrigo Kumpera

Add fast stelem.ref for interfaces too.

	* marshal.c (mono_marshal_get_virtual_stelemref): Add a custom
	wrapper for interface casts.

	This was the most frequent array kind left without a fast
	stelem.ref wrapper. During testing the only easy target
	left was arrays of arrays, but those are so rare that
	won't make a different on any workload.
上级 0c292567
...@@ -9566,12 +9566,13 @@ enum { ...@@ -9566,12 +9566,13 @@ enum {
STELEMREF_OBJECT, /*no check at all*/ STELEMREF_OBJECT, /*no check at all*/
STELEMREF_SEALED_CLASS, /*check vtable->klass->element_type */ STELEMREF_SEALED_CLASS, /*check vtable->klass->element_type */
STELEMREF_CLASS, /*only the klass->parents check*/ STELEMREF_CLASS, /*only the klass->parents check*/
STELEMREF_COMPLEX, /*arrays, interfaces, MBR or classes with variant generic args - go straight to icalls*/ STELEMREF_INTERFACE, /*interfaces without variant generic arguments. */
STELEMREF_COMPLEX, /*arrays, MBR or types with variant generic args - go straight to icalls*/
STELEMREF_KIND_COUNT STELEMREF_KIND_COUNT
}; };
static const char *strelemref_wrapper_name[] = { static const char *strelemref_wrapper_name[] = {
"object", "sealed_class", "class", "complex" "object", "sealed_class", "class", "interface", "complex"
}; };
static gboolean static gboolean
...@@ -9592,8 +9593,10 @@ get_virtual_stelemref_kind (MonoClass *element_class) ...@@ -9592,8 +9593,10 @@ get_virtual_stelemref_kind (MonoClass *element_class)
return STELEMREF_OBJECT; return STELEMREF_OBJECT;
if (is_monomorphic_array (element_class)) if (is_monomorphic_array (element_class))
return STELEMREF_SEALED_CLASS; return STELEMREF_SEALED_CLASS;
if (MONO_CLASS_IS_INTERFACE (element_class) && !mono_class_has_variant_generic_params (element_class))
return STELEMREF_INTERFACE;
/*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/ /*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
if (MONO_CLASS_IS_INTERFACE (element_class) || element_class->marshalbyref || element_class->rank || mono_class_has_variant_generic_params (element_class)) if (element_class->marshalbyref || element_class->rank || mono_class_has_variant_generic_params (element_class))
return STELEMREF_COMPLEX; return STELEMREF_COMPLEX;
if (element_class->flags & TYPE_ATTRIBUTE_SEALED) if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
return STELEMREF_SEALED_CLASS; return STELEMREF_SEALED_CLASS;
...@@ -9634,7 +9637,7 @@ load_value_class (MonoMethodBuilder *mb, int vklass) ...@@ -9634,7 +9637,7 @@ load_value_class (MonoMethodBuilder *mb, int vklass)
#if 0 #if 0
static void static void
record_vstore_2 (MonoObject *array, size_t index, MonoObject *value) record_slot_vstore (MonoObject *array, size_t index, MonoObject *value)
{ {
char *name = mono_type_get_full_name (array->vtable->klass->element_class); char *name = mono_type_get_full_name (array->vtable->klass->element_class);
printf ("slow vstore of %s\n", name); printf ("slow vstore of %s\n", name);
...@@ -9659,7 +9662,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class) ...@@ -9659,7 +9662,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
int kind; int kind;
guint32 b1, b2, b3; guint32 b1, b2, b3;
int aklass, vklass; int aklass, vklass, vtable, uiid;
int array_slot_addr; int array_slot_addr;
g_assert (array_class->rank == 1); g_assert (array_class->rank == 1);
...@@ -9712,7 +9715,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class) ...@@ -9712,7 +9715,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
#if 0 #if 0
{ {
/*Use this to debug stores that are going thru the slow path*/ /*Use this to debug/record stores that are going thru the slow path*/
MonoMethodSignature *csig; MonoMethodSignature *csig;
csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3); csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
csig->ret = &mono_defaults.void_class->byval_arg; csig->ret = &mono_defaults.void_class->byval_arg;
...@@ -9722,7 +9725,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class) ...@@ -9722,7 +9725,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldarg (mb, 1); mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_ldarg (mb, 2); mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_native_call (mb, csig, record_vstore_2); mono_mb_emit_native_call (mb, csig, record_slot_vstore);
} }
#endif #endif
...@@ -9900,6 +9903,101 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class) ...@@ -9900,6 +9903,101 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL); mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
break; break;
case STELEMREF_INTERFACE:
/*Mono *klass;
MonoVTable *vt;
unsigned uiid;
if (value == NULL)
goto store;
klass = array->obj.vtable->klass->element_class;
vt = value->vtable;
uiid = klass->interface_id;
if (uiid > vt->max_interface_id)
goto exception;
if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7))))
goto exception;
store:
mono_array_setref (array, index, value);
return;
exception:
mono_raise_exception (mono_get_exception_array_type_mismatch ());*/
array_slot_addr = mono_mb_add_local (mb, &mono_defaults.object_class->this_arg);
aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
vtable = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
uiid = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
/* ldelema (implicit bound check) */
load_array_element_address (mb);
mono_mb_emit_stloc (mb, array_slot_addr);
/* if (!value) goto do_store */
mono_mb_emit_ldarg (mb, 2);
b1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
/* klass = array->vtable->klass->element_class */
load_array_class (mb, aklass);
/* vt = value->vtable */
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_stloc (mb, vtable);
/* uiid = klass->interface_id; */
mono_mb_emit_ldloc (mb, aklass);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, interface_id));
mono_mb_emit_byte (mb, CEE_LDIND_U2);
mono_mb_emit_stloc (mb, uiid);
/*if (uiid > vt->max_interface_id)*/
mono_mb_emit_ldloc (mb, uiid);
mono_mb_emit_ldloc (mb, vtable);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
mono_mb_emit_byte (mb, CEE_LDIND_I);
b2 = mono_mb_emit_branch (mb, CEE_BGT_UN);
/* if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7)))) */
/*vt->interface_bitmap*/
mono_mb_emit_ldloc (mb, vtable);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, interface_bitmap));
mono_mb_emit_byte (mb, CEE_LDIND_I);
/*uiid >> 3*/
mono_mb_emit_ldloc (mb, uiid);
mono_mb_emit_icon (mb, 3);
mono_mb_emit_byte (mb, CEE_SHR_UN);
/*vt->interface_bitmap [(uiid) >> 3]*/
mono_mb_emit_byte (mb, CEE_ADD); /*interface_bitmap is a guint8 array*/
mono_mb_emit_byte (mb, CEE_LDIND_U1);
/*(1 << ((uiid)&7)))*/
mono_mb_emit_icon (mb, 1);
mono_mb_emit_ldloc (mb, uiid);
mono_mb_emit_icon (mb, 7);
mono_mb_emit_byte (mb, CEE_AND);
mono_mb_emit_byte (mb, CEE_SHL);
/*bitwise and the whole thing*/
mono_mb_emit_byte (mb, CEE_AND);
b3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
/* do_store: */
mono_mb_patch_branch (mb, b1);
mono_mb_emit_ldloc (mb, array_slot_addr);
mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_byte (mb, CEE_STIND_REF);
mono_mb_emit_byte (mb, CEE_RET);
/* do_exception: */
mono_mb_patch_branch (mb, b2);
mono_mb_patch_branch (mb, b3);
mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
break;
default: default:
mono_mb_emit_ldarg (mb, 0); mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldarg (mb, 1); mono_mb_emit_ldarg (mb, 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册