Author: massi
Date: 2008-02-06 11:16:09 -0500 (Wed, 06 Feb 2008)
New Revision: 95036
Modified:
trunk/mono/mono/metadata/ChangeLog
trunk/mono/mono/metadata/class.c
Log:
*class.c:
mono_class_setup_vtable_general: rewrote the way in which interface
methods are added to vtables. Makes bug-77127.exe pass, and hopefully
makes the code more maintainable.
For now the old code is still there, and can be activated setting
the env var "USE_NEW_INTERFACE_VTABLE_CODE".
Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog 2008-02-06 16:15:30 UTC (rev 95035)
+++ trunk/mono/mono/metadata/ChangeLog 2008-02-06 16:16:09 UTC (rev 95036)
@@ -1,3 +1,11 @@
+2008-02-06 Massimiliano Mantione <[EMAIL PROTECTED]>
+ *class.c:
+ mono_class_setup_vtable_general: rewrote the way in which interface
+ methods are added to vtables. Makes bug-77127.exe pass, and hopefully
+ makes the code more maintainable.
+ For now the old code is still there, and can be activated setting
+ the env var "USE_NEW_INTERFACE_VTABLE_CODE".
+
2008-02-06 Rodrigo Kumpera <[EMAIL PROTECTED]>
* verify.c: guarded some debug functions around and #ifdef.
Modified: trunk/mono/mono/metadata/class.c
===================================================================
--- trunk/mono/mono/metadata/class.c 2008-02-06 16:15:30 UTC (rev 95035)
+++ trunk/mono/mono/metadata/class.c 2008-02-06 16:16:09 UTC (rev 95036)
@@ -1760,9 +1760,11 @@
printf ("Packed interface table for class %s has size %d\n",
klass->name, klass->interface_offsets_count);
for (i = 0; i < klass->interface_offsets_count; i++)
- printf (" [%d][UUID %d][SLOT %d] interface %s\n", i,
+ printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface
%s.%s\n", i,
klass->interfaces_packed [i]->interface_id,
klass->interface_offsets_packed [i],
+ klass->interfaces_packed [i]->method.count,
+ klass->interfaces_packed [i]->name_space,
klass->interfaces_packed [i]->name );
printf ("Interface flags: ");
for (i = 0; i <= klass->max_interface_id; i++)
@@ -1782,6 +1784,12 @@
for (i = 0; i < ifaces->len; i++) {
MonoClass *ic = g_ptr_array_index (ifaces, i);
printf (" [UIID %d] interface %s\n",
ic->interface_id, ic->name);
+ printf (" [%03d][UUID %03d][SLOT %03d][SIZE
%03d] interface %s.%s\n", i,
+ ic->interface_id,
+ mono_class_interface_offset
(klass, ic),
+ ic->method.count,
+ ic->name_space,
+ ic->name );
}
g_ptr_array_free (ifaces, TRUE);
}
@@ -2247,6 +2255,267 @@
}
}
+
+static int __use_new_interface_vtable_code = -1;
+static gboolean
+use_new_interface_vtable_code (void) {
+ if (__use_new_interface_vtable_code == -1) {
+ char *env_var = getenv ("USE_NEW_INTERFACE_VTABLE_CODE");
+ if (env_var == NULL) {
+ __use_new_interface_vtable_code = FALSE;
+ } else {
+ if ((strcmp (env_var, "0") == 0) || (strcmp (env_var,
"false") == 0) || (strcmp (env_var, "FALSE") == 0)) {
+ __use_new_interface_vtable_code = FALSE;
+ } else {
+ __use_new_interface_vtable_code = TRUE;
+ }
+ }
+ }
+ return __use_new_interface_vtable_code;
+}
+
+
+#define DEBUG_INTERFACE_VTABLE_CODE 0
+#define TRACE_INTERFACE_VTABLE_CODE 0
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+#define DEBUG_INTERFACE_VTABLE(stmt) do {\
+ stmt;\
+} while (0)
+#else
+#define DEBUG_INTERFACE_VTABLE(stmt)
+#endif
+
+#if TRACE_INTERFACE_VTABLE_CODE
+#define TRACE_INTERFACE_VTABLE(stmt) do {\
+ stmt;\
+} while (0)
+#else
+#define TRACE_INTERFACE_VTABLE(stmt)
+#endif
+
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+static char*
+mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean
include_namespace)
+{
+ int i;
+ char *result;
+ GString *res = g_string_new ("");
+
+ g_string_append_c (res, '(');
+ for (i = 0; i < sig->param_count; ++i) {
+ if (i > 0)
+ g_string_append_c (res, ',');
+ mono_type_get_desc (res, sig->params [i], include_namespace);
+ }
+ g_string_append (res, ")=>");
+ if (sig->ret != NULL) {
+ mono_type_get_desc (res, sig->ret, include_namespace);
+ } else {
+ g_string_append (res, "NULL");
+ }
+ result = res->str;
+ g_string_free (res, FALSE);
+ return result;
+}
+static void
+print_method_signatures (MonoMethod *im, MonoMethod *cm) {
+ char *im_sig = mono_signature_get_full_desc (mono_method_signature
(im), TRUE);
+ char *cm_sig = mono_signature_get_full_desc (mono_method_signature
(cm), TRUE);
+ printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
+ g_free (im_sig);
+ g_free (cm_sig);
+
+}
+
+#endif
+static gboolean
+check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod
*cm, gboolean require_newslot, gboolean
interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean
security_enabled) {
+ if (strcmp (im->name, cm->name) == 0) {
+ if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
+ TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK
FAILED]"));
+ return FALSE;
+ }
+ if (! slot_is_empty) {
+ if (require_newslot) {
+ if (!
interface_is_explicitly_implemented_by_class) {
+ TRACE_INTERFACE_VTABLE (printf ("[NOT
EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
+ return FALSE;
+ }
+ if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
+ TRACE_INTERFACE_VTABLE (printf
("[NEWSLOT CHECK FAILED]"));
+ return FALSE;
+ }
+ } else {
+ TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT
REFUSED]"));
+ }
+ }
+ if (! mono_metadata_signature_equal (mono_method_signature
(cm), mono_method_signature (im))) {
+ TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK
FAILED "));
+ TRACE_INTERFACE_VTABLE (print_method_signatures (im,
cm));
+ TRACE_INTERFACE_VTABLE (printf ("]"));
+ return FALSE;
+ }
+ TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
+ /* CAS - SecurityAction.InheritanceDemand on interface */
+ if (security_enabled && (im->flags &
METHOD_ATTRIBUTE_HAS_SECURITY)) {
+ mono_secman_inheritancedemand_method (cm, im);
+ }
+
+ if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ check_core_clr_override_method (class, cm, im);
+ TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
+ return TRUE;
+ } else {
+ MonoClass *ic = im->klass;
+ const char *ic_name_space = ic->name_space;
+ const char *ic_name = ic->name;
+ char *subname;
+
+ if (! require_newslot) {
+ TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD
REFUSED]"));
+ return FALSE;
+ }
+ if (cm->klass->rank == 0) {
+ TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
+ return FALSE;
+ }
+ if (! mono_metadata_signature_equal (mono_method_signature
(cm), mono_method_signature (im))) {
+ TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE
CHECK FAILED "));
+ TRACE_INTERFACE_VTABLE (print_method_signatures (im,
cm));
+ TRACE_INTERFACE_VTABLE (printf ("]"));
+ return FALSE;
+ }
+ if (mono_class_get_image (ic) != mono_defaults.corlib) {
+ TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB
CHECK FAILED]"));
+ return FALSE;
+ }
+ if ((ic_name_space == NULL) || (strcmp (ic_name_space,
"System.Collections.Generic") != 0)) {
+ TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE
CHECK FAILED]"));
+ return FALSE;
+ }
+ if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") !=
0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1")
!= 0))) {
+ TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK
FAILED]"));
+ return FALSE;
+ }
+
+ subname = strstr (cm->name, ic_name_space);
+ if (subname != cm->name) {
+ TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE
CHECK FAILED]"));
+ return FALSE;
+ }
+ subname += strlen (ic_name_space);
+ if (subname [0] != '.') {
+ TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK
FAILED]"));
+ return FALSE;
+ }
+ subname ++;
+ if (strstr (subname, ic_name) != subname) {
+ TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME
CHECK FAILED]"));
+ return FALSE;
+ }
+ subname += strlen (ic_name);
+ if (subname [0] != '.') {
+ TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK
FAILED]"));
+ return FALSE;
+ }
+ subname ++;
+ if (strcmp (subname, im->name) != 0) {
+ TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK
FAILED]"));
+ return FALSE;
+ }
+
+ TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED
CASE)]"));
+ /* CAS - SecurityAction.InheritanceDemand on interface */
+ if (security_enabled && (im->flags &
METHOD_ATTRIBUTE_HAS_SECURITY)) {
+ mono_secman_inheritancedemand_method (cm, im);
+ }
+
+ if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ check_core_clr_override_method (class, cm, im);
+
+ TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK
OK]"));
+ return TRUE;
+ }
+}
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+static void
+foreach_override (gpointer key, gpointer value, gpointer user_data) {
+ MonoMethod *method = key;
+ MonoMethod *override = value;
+ MonoClass *method_class = mono_method_get_class (method);
+ MonoClass *override_class = mono_method_get_class (override);
+
+ printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
+ mono_class_get_namespace (method_class),
mono_class_get_name (method_class), mono_method_get_name (method),
+ mono_class_get_namespace (override_class),
mono_class_get_name (override_class), mono_method_get_name (override));
+}
+static void
+print_overrides (GHashTable *override_map, const char *message) {
+ if (override_map) {
+ printf ("Override map \"%s\" START:\n", message);
+ g_hash_table_foreach (override_map, foreach_override, NULL);
+ printf ("Override map \"%s\" END.\n", message);
+ } else {
+ printf ("Override map \"%s\" EMPTY.\n", message);
+ }
+}
+static void
+print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int
first_non_interface_slot, const char *message, gboolean print_interfaces) {
+ char *full_name = mono_type_full_name (&class->byval_arg);
+ int i;
+ int parent_size;
+
+ printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name,
message, size);
+
+ if (print_interfaces) {
+ print_implemented_interfaces (class);
+ printf ("* Interfaces for class '%s' done.\nStarting vtable
(size %d):\n", full_name, size);
+ }
+
+ if (class->parent) {
+ parent_size = class->parent->vtable_size;
+ } else {
+ parent_size = 0;
+ }
+ for (i = 0; i < size; ++i) {
+ MonoMethod *cm = vtable [i];
+ if (cm) {
+ char *cm_name = mono_method_full_name (cm, TRUE);
+ char newness = (i < parent_size) ? 'O' : ((i <
first_non_interface_slot) ? 'I' : 'N');
+ printf (" [%c][%03d][INDEX %03d] %s\n", newness, i,
cm->slot, cm_name);
+ g_free (cm_name);
+ }
+ }
+
+ g_free (full_name);
+}
+#endif
+
+static void
+print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic,
MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
+ int index;
+ char *method_signature;
+
+ for (index = 0; index < onum; ++index) {
+ g_print (" at slot %d: %s (%d) overrides %s (%d)\n", im_slot,
overrides [index*2+1]->name,
+ overrides [index*2+1]->slot, overrides
[index*2]->name, overrides [index*2]->slot);
+ }
+ method_signature = mono_signature_get_desc (mono_method_signature (im),
FALSE);
+ printf ("no implementation for interface method %s::%s(%s) in class
%s.%s\n",
+ mono_type_get_name (&ic->byval_arg), im->name,
method_signature, class->name_space, class->name);
+ g_free (method_signature);
+ for (index = 0; index < class->method.count; ++index) {
+ MonoMethod *cm = class->methods [index];
+ method_signature = mono_signature_get_desc
(mono_method_signature (cm), TRUE);
+
+ printf ("METHOD %s(%s)\n", cm->name, method_signature);
+ g_free (method_signature);
+ }
+}
+
/*
* LOCKING: this is supposed to be called with the loader lock held.
*/
@@ -2259,6 +2528,9 @@
GPtrArray *ifaces, *pifaces = NULL;
GHashTable *override_map = NULL;
gboolean security_enabled = mono_is_security_manager_active ();
+#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
+ int first_non_interface_slot;
+#endif
if (class->vtable)
return;
@@ -2270,6 +2542,7 @@
max_vtsize += ic->method.count;
}
g_ptr_array_free (ifaces, TRUE);
+ ifaces = NULL;
}
if (class->parent) {
@@ -2288,10 +2561,45 @@
cur_slot = setup_interface_offsets (class, cur_slot);
max_iid = class->max_interface_id;
+ DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
- if (class->parent && class->parent->vtable_size)
- memcpy (vtable, class->parent->vtable, sizeof (gpointer) *
class->parent->vtable_size);
+ if (use_new_interface_vtable_code ()) {
+ if (class->parent && class->parent->vtable_size) {
+ MonoClass *parent = class->parent;
+ int i;
+
+ memcpy (vtable, parent->vtable, sizeof (gpointer) *
parent->vtable_size);
+
+ // Also inherit parent interface vtables, just as a
starting point.
+ // This is needed otherwise bug-77127.exe fails when
the property methods
+ // have different names in the iterface and the class,
because for child
+ // classes the ".override" information is not used
anymore.
+ for (i = 0; i < parent->interface_offsets_count; i++) {
+ MonoClass *parent_interface =
parent->interfaces_packed [i];
+ int interface_offset =
mono_class_interface_offset (class, parent_interface);
+
+ if (interface_offset >= parent->vtable_size) {
+ int parent_interface_offset =
mono_class_interface_offset (parent, parent_interface);
+ int j;
+
+ mono_class_setup_methods
(parent_interface);
+ TRACE_INTERFACE_VTABLE (printf ("
+++ Inheriting interface %s.%s\n", parent_interface->name_space,
parent_interface->name));
+ for (j = 0; j <
parent_interface->method.count; j++) {
+ vtable [interface_offset + j] =
parent->vtable [parent_interface_offset + j];
+ TRACE_INTERFACE_VTABLE (printf
(" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
+
parent_interface_offset + j, parent_interface_offset, j,
+
interface_offset + j, interface_offset, j));
+ }
+ }
+
+ }
+ }
+ } else {
+ if (class->parent && class->parent->vtable_size)
+ memcpy (vtable, class->parent->vtable, sizeof
(gpointer) * class->parent->vtable_size);
+ }
+ TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot,
first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
/* override interface methods */
for (i = 0; i < onum; i++) {
MonoMethod *decl = overrides [i*2];
@@ -2311,231 +2619,353 @@
check_core_clr_override_method (class, vtable
[dslot], decl);
}
}
+ TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER
OVERRIDING INTERFACE METHODS"));
+ TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot,
first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
- for (k = class; k ; k = k->parent) {
- int nifaces = 0;
-
- ifaces = mono_class_get_implemented_interfaces (k);
- if (ifaces) {
- nifaces = ifaces->len;
- if (k->generic_class) {
- pifaces = mono_class_get_implemented_interfaces
(
- k->generic_class->container_class);
- g_assert (pifaces && (pifaces->len == nifaces));
+ if (use_new_interface_vtable_code ()) {
+ // Loop on all implemented interfaces...
+ for (i = 0; i < class->interface_offsets_count; i++) {
+ MonoClass *parent = class->parent;
+ int ic_offset;
+ gboolean interface_is_explicitly_implemented_by_class;
+ int im_index;
+
+ ic = class->interfaces_packed [i];
+ ic_offset = mono_class_interface_offset (class, ic);
+
+ // Check if this interface is explicitly implemented
(instead of just inherited)
+ if (parent != NULL) {
+ int implemented_interfaces_index;
+ interface_is_explicitly_implemented_by_class =
FALSE;
+ for (implemented_interfaces_index = 0;
implemented_interfaces_index < class->interface_count;
implemented_interfaces_index++) {
+ if (ic == class->interfaces
[implemented_interfaces_index]) {
+
interface_is_explicitly_implemented_by_class = TRUE;
+ break;
+ }
+ }
+ } else {
+ interface_is_explicitly_implemented_by_class =
TRUE;
}
+
+ // Loop on all interface methods...
+ for (im_index = 0; im_index < ic->method.count;
im_index++) {
+ MonoMethod *im = ic->methods [im_index];
+ int im_slot = ic_offset + im->slot;
+ MonoMethod *override_im = (override_map !=
NULL) ? g_hash_table_lookup (override_map, im) : NULL;
+
+ // If there is an explicit implementation, just
use it right away,
+ // otherwise look for a matching method
+ if (override_im == NULL) {
+ int cm_index;
+
+ // First look for a suitable method
among the class methods
+ for (cm_index = 0; cm_index <
class->method.count; cm_index++) {
+ MonoMethod *cm = class->methods
[cm_index];
+
+ TRACE_INTERFACE_VTABLE (printf
(" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT
IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name,
im->name, cm->klass->name_space, cm->klass->name, cm->name,
interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
+ if ((cm->flags &
METHOD_ATTRIBUTE_VIRTUAL) && check_interface_method_override (class, im, cm,
TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL),
security_enabled)) {
+ TRACE_INTERFACE_VTABLE
(printf ("[check ok]: ASSIGNING"));
+ vtable [im_slot] = cm;
+ /* Why do we need this?
*/
+ if (cm->slot < 0) {
+ cm->slot =
im_slot;
+ }
+ }
+ TRACE_INTERFACE_VTABLE (printf
("\n"));
+ }
+
+ // If the slot is still empty, look in
all the inherited virtual methods...
+ if ((vtable [im_slot] == NULL) &&
class->parent != NULL) {
+ MonoClass *parent =
class->parent;
+ // Reverse order, so that last
added methods are preferred
+ for (cm_index =
parent->vtable_size - 1; cm_index >= 0; cm_index--) {
+ MonoMethod *cm =
parent->vtable [cm_index];
+
+ TRACE_INTERFACE_VTABLE
((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor)
method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name,
cm->klass->name_space, cm->klass->name, cm->name));
+ if ((cm != NULL) &&
check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE,
security_enabled)) {
+
TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
+ vtable
[im_slot] = cm;
+ /* Why do we
need this? */
+ if (cm->slot <
0) {
+
cm->slot = im_slot;
+ }
+ break;
+ }
+ TRACE_INTERFACE_VTABLE
((cm != NULL) && printf ("\n"));
+ }
+ }
+ } else {
+ g_assert (vtable [im_slot] ==
override_im);
+ }
+ }
}
- for (i = 0; i < nifaces; i++) {
- MonoClass *pic = NULL;
- int j, l, io;
+
+ // If the class is not abstract, check that all its interface
slots are full.
+ // The check is done here and not directly at the end of the
loop above because
+ // it can happen (for injected generic array interfaces) that
the same slot is
+ // processed multiple times (those interfaces have overlapping
slots), and it
+ // will not always be the first pass the one that fills the
slot.
+ if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ for (i = 0; i < class->interface_offsets_count; i++) {
+ int ic_offset;
+ int im_index;
+
+ ic = class->interfaces_packed [i];
+ ic_offset = mono_class_interface_offset (class,
ic);
+
+ for (im_index = 0; im_index < ic->method.count;
im_index++) {
+ MonoMethod *im = ic->methods [im_index];
+ int im_slot = ic_offset + im->slot;
+
+ TRACE_INTERFACE_VTABLE (printf ("
[class is not abstract, checking slot %d for interface '%s'.'%s', method %s,
slot check is %d]\n",
+ im_slot,
ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
+ if (vtable [im_slot] == NULL) {
+
print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides,
onum);
+ mono_class_set_failure (class,
MONO_EXCEPTION_TYPE_LOAD, NULL);
+ if (override_map)
+ g_hash_table_destroy
(override_map);
+ return;
+ }
+ }
+ }
+ }
+ } else {
+ for (k = class; k ; k = k->parent) {
+ int nifaces = 0;
- ic = g_ptr_array_index (ifaces, i);
- if (pifaces)
- pic = g_ptr_array_index (pifaces, i);
- g_assert (ic->interface_id <= k->max_interface_id);
- io = mono_class_interface_offset (k, ic);
+ ifaces = mono_class_get_implemented_interfaces (k);
+ if (ifaces) {
+ nifaces = ifaces->len;
+ if (k->generic_class) {
+ pifaces =
mono_class_get_implemented_interfaces (
+
k->generic_class->container_class);
+ g_assert (pifaces && (pifaces->len ==
nifaces));
+ }
+ }
+ for (i = 0; i < nifaces; i++) {
+ MonoClass *pic = NULL;
+ int j, l, io;
- g_assert (io >= 0);
- g_assert (io <= max_vtsize);
+ ic = g_ptr_array_index (ifaces, i);
+ if (pifaces)
+ pic = g_ptr_array_index (pifaces, i);
+ g_assert (ic->interface_id <=
k->max_interface_id);
+ io = mono_class_interface_offset (k, ic);
- if (k == class) {
- mono_class_setup_methods (ic);
- for (l = 0; l < ic->method.count; l++) {
- MonoMethod *im = ic->methods [l];
+ g_assert (io >= 0);
+ g_assert (io <= max_vtsize);
- if (vtable [io + l] && !(vtable [io +
l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
- continue;
+ if (k == class) {
+ mono_class_setup_methods (ic);
+ for (l = 0; l < ic->method.count; l++) {
+ MonoMethod *im = ic->methods
[l];
- for (j = 0; j < class->method.count;
++j) {
- MonoMethod *cm = class->methods
[j];
- if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL) ||
- !((cm->flags &
METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
- !(cm->flags &
METHOD_ATTRIBUTE_NEW_SLOT))
+ if (vtable [io + l] && !(vtable
[io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
continue;
- if (!strcmp(cm->name, im->name)
&&
-
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im))) {
- /* CAS -
SecurityAction.InheritanceDemand on interface */
- if (security_enabled &&
(im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-
mono_secman_inheritancedemand_method (cm, im);
- }
+ for (j = 0; j <
class->method.count; ++j) {
+ MonoMethod *cm =
class->methods [j];
+ if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL) ||
+ !((cm->flags &
METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
+ !(cm->flags &
METHOD_ATTRIBUTE_NEW_SLOT))
+ continue;
+ if (!strcmp(cm->name,
im->name) &&
+
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im))) {
- if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-
check_core_clr_override_method (class, cm, im);
+ /* CAS -
SecurityAction.InheritanceDemand on interface */
+ if
(security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+
mono_secman_inheritancedemand_method (cm, im);
+ }
- g_assert (io + l <=
max_vtsize);
- vtable [io + l] = cm;
+ if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+
check_core_clr_override_method (class, cm, im);
+
+ g_assert (io +
l <= max_vtsize);
+ vtable [io + l]
= cm;
+
TRACE_INTERFACE_VTABLE (printf (" [NOA] Filling slot %d (%d+%d) with method
'%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name,
cm->name));
+
TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+
TRACE_INTERFACE_VTABLE (printf ("\n"));
+ }
}
}
+ } else {
+ /* already implemented */
+ if (io >= k->vtable_size)
+ continue;
}
- } else {
- /* already implemented */
- if (io >= k->vtable_size)
- continue;
- }
- // Override methods with the same fully qualified name
- for (l = 0; l < ic->method.count; l++) {
- MonoMethod *im = ic->methods [l];
- char *qname, *fqname, *cname, *the_cname;
- MonoClass *k1;
-
- if (vtable [io + l])
- continue;
-
- if (pic) {
- the_cname = mono_type_get_name_full
(&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
- cname = the_cname;
- } else {
- the_cname = NULL;
- cname = (char*)ic->name;
- }
+ // Override methods with the same fully
qualified name
+ for (l = 0; l < ic->method.count; l++) {
+ MonoMethod *im = ic->methods [l];
+ char *qname, *fqname, *cname,
*the_cname;
+ MonoClass *k1;
- qname = g_strconcat (cname, ".", im->name,
NULL);
- if (ic->name_space && ic->name_space [0])
- fqname = g_strconcat (ic->name_space,
".", cname, ".", im->name, NULL);
- else
- fqname = NULL;
+ if (vtable [io + l])
+ continue;
- for (k1 = class; k1; k1 = k1->parent) {
- for (j = 0; j < k1->method.count; ++j) {
- MonoMethod *cm = k1->methods
[j];
+ if (pic) {
+ the_cname =
mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
+ cname = the_cname;
+ } else {
+ the_cname = NULL;
+ cname = (char*)ic->name;
+ }
+
+ qname = g_strconcat (cname, ".",
im->name, NULL);
+ if (ic->name_space && ic->name_space
[0])
+ fqname = g_strconcat
(ic->name_space, ".", cname, ".", im->name, NULL);
+ else
+ fqname = NULL;
- if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL))
- continue;
+ for (k1 = class; k1; k1 = k1->parent) {
+ for (j = 0; j <
k1->method.count; ++j) {
+ MonoMethod *cm =
k1->methods [j];
- if (((fqname && !strcmp
(cm->name, fqname)) || !strcmp (cm->name, qname)) &&
-
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im)) &&
- ((vtable [io +
l] == NULL) || mono_class_is_subclass_of (cm->klass, vtable [io + l]->klass,
FALSE))) {
+ if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL))
+ continue;
- /* CAS -
SecurityAction.InheritanceDemand on interface */
- if (security_enabled &&
(im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-
mono_secman_inheritancedemand_method (cm, im);
- }
+ if (((fqname && !strcmp
(cm->name, fqname)) || !strcmp (cm->name, qname)) &&
+
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im)) &&
+
((vtable [io + l] == NULL) || mono_class_is_subclass_of (cm->klass, vtable [io
+ l]->klass, FALSE))) {
- if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-
check_core_clr_override_method (class, cm, im);
+ /* CAS -
SecurityAction.InheritanceDemand on interface */
+ if
(security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+
mono_secman_inheritancedemand_method (cm, im);
+ }
- g_assert (io + l <=
max_vtsize);
- vtable [io + l] = cm;
- break;
+ if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+
check_core_clr_override_method (class, cm, im);
+
+ g_assert (io +
l <= max_vtsize);
+ vtable [io + l]
= cm;
+
TRACE_INTERFACE_VTABLE (printf (" [FQN] Filling slot %d (%d+%d) with method
'%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name,
cm->name));
+
TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+
TRACE_INTERFACE_VTABLE (printf ("\n"));
+ break;
+ }
}
}
+ g_free (the_cname);
+ g_free (qname);
+ g_free (fqname);
}
- g_free (the_cname);
- g_free (qname);
- g_free (fqname);
- }
- // Override methods with the same name
- for (l = 0; l < ic->method.count; l++) {
- MonoMethod *im = ic->methods [l];
- MonoClass *k1;
+ // Override methods with the same name
+ for (l = 0; l < ic->method.count; l++) {
+ MonoMethod *im = ic->methods [l];
+ MonoClass *k1;
- g_assert (io + l <= max_vtsize);
+ g_assert (io + l <= max_vtsize);
- if (vtable [io + l] && !(vtable [io + l]->flags
& METHOD_ATTRIBUTE_ABSTRACT))
- continue;
-
- for (k1 = class; k1; k1 = k1->parent) {
- for (j = 0; j < k1->method.count; ++j) {
- MonoMethod *cm = k1->methods
[j];
-
- if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL) ||
- !(cm->flags &
METHOD_ATTRIBUTE_PUBLIC))
- continue;
+ if (vtable [io + l] && !(vtable [io +
l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
+ continue;
- if (!strcmp(cm->name, im->name)
&&
-
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im))) {
+ for (k1 = class; k1; k1 = k1->parent) {
+ for (j = 0; j <
k1->method.count; ++j) {
+ MonoMethod *cm =
k1->methods [j];
- /* CAS -
SecurityAction.InheritanceDemand on interface */
- if (security_enabled &&
(im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-
mono_secman_inheritancedemand_method (cm, im);
- }
+ if (!(cm->flags &
METHOD_ATTRIBUTE_VIRTUAL) ||
+ !(cm->flags &
METHOD_ATTRIBUTE_PUBLIC))
+ continue;
+
+ if (!strcmp(cm->name,
im->name) &&
+
mono_metadata_signature_equal (mono_method_signature (cm),
mono_method_signature (im))) {
- if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-
check_core_clr_override_method (class, cm, im);
+ /* CAS -
SecurityAction.InheritanceDemand on interface */
+ if
(security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+
mono_secman_inheritancedemand_method (cm, im);
+ }
- g_assert (io + l <=
max_vtsize);
- vtable [io + l] = cm;
+ if
(mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+
check_core_clr_override_method (class, cm, im);
+
+ g_assert (io +
l <= max_vtsize);
+ vtable [io + l]
= cm;
+
TRACE_INTERFACE_VTABLE (printf (" [SQN] Filling slot %d (%d+%d) with method
'%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name,
cm->name));
+
TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+
TRACE_INTERFACE_VTABLE (printf ("\n"));
+ break;
+ }
+
+ }
+ g_assert (io + l <= max_vtsize);
+ if (vtable [io + l] && !(vtable
[io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
break;
- }
-
}
- g_assert (io + l <= max_vtsize);
- if (vtable [io + l] && !(vtable [io +
l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
- break;
}
- }
- if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
- for (l = 0; l < ic->method.count; l++) {
- char *msig;
- MonoMethod *im = ic->methods [l];
- if (im->flags & METHOD_ATTRIBUTE_STATIC)
- continue;
- g_assert (io + l <= max_vtsize);
+ if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ for (l = 0; l < ic->method.count; l++) {
+ char *msig;
+ MonoMethod *im = ic->methods
[l];
+ if (im->flags &
METHOD_ATTRIBUTE_STATIC)
+ continue;
+ g_assert (io + l <= max_vtsize);
- /*
- * If one of our parents already
implements this interface
- * we can inherit the implementation.
- */
- if (!(vtable [io + l])) {
- MonoClass *parent =
class->parent;
-
- for (; parent; parent =
parent->parent) {
- if
(MONO_CLASS_IMPLEMENTS_INTERFACE (parent, ic->interface_id) &&
-
parent->vtable) {
- vtable [io + l]
= parent->vtable [mono_class_interface_offset (parent, ic) + l];
+ /*
+ * If one of our parents
already implements this interface
+ * we can inherit the
implementation.
+ */
+ if (!(vtable [io + l])) {
+ MonoClass *parent =
class->parent;
+
+ for (; parent; parent =
parent->parent) {
+ if
(MONO_CLASS_IMPLEMENTS_INTERFACE (parent, ic->interface_id) &&
+
parent->vtable) {
+ vtable
[io + l] = parent->vtable [mono_class_interface_offset (parent, ic) + l];
+
TRACE_INTERFACE_VTABLE (printf (" [INH] Filling slot %d (%d+%d) with method
'%s'.'%s':'%s'\n", io + l, io, l, vtable [io + l]->klass->name_space, vtable
[io + l]->klass->name, vtable [io + l]->name));
+ }
}
}
- }
- if (!(vtable [io + l])) {
- for (j = 0; j < onum; ++j) {
- g_print (" at slot %d:
%s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name,
- overrides
[j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
- }
- msig = mono_signature_get_desc
(mono_method_signature (im), FALSE);
- printf ("no implementation for
interface method %s::%s(%s) in class %s.%s\n",
- mono_type_get_name
(&ic->byval_arg), im->name, msig, class->name_space, class->name);
- g_free (msig);
- for (j = 0; j <
class->method.count; ++j) {
- MonoMethod *cm =
class->methods [j];
- msig =
mono_signature_get_desc (mono_method_signature (cm), TRUE);
-
- printf ("METHOD
%s(%s)\n", cm->name, msig);
+ if (!(vtable [io + l])) {
+ for (j = 0; j < onum;
++j) {
+ g_print (" at
slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name,
+
overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
+ }
+ msig =
mono_signature_get_desc (mono_method_signature (im), FALSE);
+ printf ("no
implementation for interface method %s::%s(%s) in class %s.%s\n",
+
mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space,
class->name);
g_free (msig);
- }
+ for (j = 0; j <
class->method.count; ++j) {
+ MonoMethod *cm
= class->methods [j];
+ msig =
mono_signature_get_desc (mono_method_signature (cm), TRUE);
+
+ printf ("METHOD
%s(%s)\n", cm->name, msig);
+ g_free (msig);
+ }
- mono_class_set_failure (class,
MONO_EXCEPTION_TYPE_LOAD, NULL);
+ mono_class_set_failure
(class, MONO_EXCEPTION_TYPE_LOAD, NULL);
- if (ifaces)
- g_ptr_array_free
(ifaces, TRUE);
- if (override_map)
- g_hash_table_destroy
(override_map);
+ if (ifaces)
+
g_ptr_array_free (ifaces, TRUE);
+ if (override_map)
+
g_hash_table_destroy (override_map);
- return;
+ return;
+ }
}
}
- }
-
- for (l = 0; l < ic->method.count; l++) {
- MonoMethod *im = vtable [io + l];
+
+ for (l = 0; l < ic->method.count; l++) {
+ MonoMethod *im = vtable [io + l];
- if (im) {
- g_assert (io + l <= max_vtsize);
- if (im->slot < 0) {
- /* FIXME: why do we need this ?
*/
- im->slot = io + l;
- /* g_assert_not_reached (); */
+ if (im) {
+ g_assert (io + l <= max_vtsize);
+ if (im->slot < 0) {
+ /* FIXME: why do we
need this ? */
+ im->slot = io + l;
+ /* g_assert_not_reached
(); */
+ }
}
}
}
- }
- if (ifaces)
- g_ptr_array_free (ifaces, TRUE);
- }
+ if (ifaces)
+ g_ptr_array_free (ifaces, TRUE);
+ }
+ }
+ TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot,
first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
for (i = 0; i < class->method.count; ++i) {
MonoMethod *cm;
@@ -2652,6 +3082,7 @@
memcpy (class->vtable, vtable, sizeof (gpointer) *
class->vtable_size);
}
+ DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable,
class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
if (mono_print_vtable) {
int icount = 0;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches