* Author:
* Miguel de Icaza (miguel@ximian.com)
*
- * (C) 2001-2006 Novell, Inc.
- *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
*/
#include <config.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <mono/metadata/attrdefs.h>
#include <mono/metadata/gc-internal.h>
#include <mono/metadata/verify-internals.h>
+#include <mono/metadata/mono-debug.h>
#include <mono/utils/mono-counters.h>
MonoStats mono_stats;
static int generic_array_methods (MonoClass *class);
static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
+static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
+
void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
* The same as mono_class_inflate_generic_type, but allocates the MonoType
* from mempool if it is non-NULL. If it is NULL, the MonoType is
* allocated on the heap and is owned by the caller.
+ * The returned type can potentially be the same as TYPE, so it should not be
+ * modified by the caller, and it should be freed using mono_metadata_free_type ().
*/
MonoType*
mono_class_inflate_generic_type_with_mempool (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context)
if (context)
inflated = inflate_generic_type (mempool, type, context);
- if (!inflated)
- return mono_metadata_type_dup (mempool, type);
+ if (!inflated) {
+ MonoType *shared = mono_metadata_get_shared_type (type);
+
+ if (shared) {
+ return shared;
+ } else {
+ return mono_metadata_type_dup (mempool, type);
+ }
+ }
mono_stats.inflated_type_count++;
return inflated;
return mono_class_inflate_generic_type_with_mempool (NULL, type, context);
}
+/*
+ * mono_class_inflate_generic_type_with_mempool_no_copy:
+ *
+ * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
+ * was done.
+ */
+static MonoType*
+mono_class_inflate_generic_type_with_mempool_no_copy (MonoMemPool *mempool, MonoType *type, MonoGenericContext *context)
+{
+ MonoType *inflated = NULL;
+
+ if (context)
+ inflated = inflate_generic_type (mempool, type, context);
+
+ if (!inflated)
+ return type;
+
+ mono_stats.inflated_type_count++;
+ return inflated;
+}
static MonoGenericContext
inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
class->min_align = 1;
}
+ if (class->simd_type)
+ class->min_align = 16;
+
/* Get the real size */
explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
g_assert (container);
mono_class_setup_fields (gklass);
+
+ if (gklass->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
}
/*
if (class->generic_class) {
MonoClassField *gfield = &gklass->fields [i];
- MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
- ifield->generic_type = gfield->type;
- field->name = gfield->name;
- field->generic_info = ifield;
+ field->name = mono_field_get_name (gfield);
/*This memory must come from the image mempool as we don't have a chance to free it.*/
- field->type = mono_class_inflate_generic_type_with_mempool (class->image->mempool, gfield->type, mono_class_get_context (class));
- field->type->attrs = gfield->type->attrs;
+ field->type = mono_class_inflate_generic_type_with_mempool_no_copy (class->image->mempool, gfield->type, mono_class_get_context (class));
+ g_assert (field->type->attrs == gfield->type->attrs);
if (mono_field_is_deleted (field))
continue;
field->offset = gfield->offset;
- field->data = gfield->data;
} else {
- guint32 rva;
const char *sig;
guint32 cols [MONO_FIELD_SIZE];
field->offset = offset;
if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
g_warning ("%s not initialized correctly (missing field layout info for %s)",
- class->name, field->name);
- }
-
- if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
- mono_metadata_field_info (m, idx, NULL, &rva, NULL);
- if (!rva)
- g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
- field->data = mono_image_rva_map (class->image, rva);
+ class->name, mono_field_get_name (field));
}
}
}
if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
- (strcmp (field->name, "$PRIVATE$") == 0)) {
+ (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
/* This field is a hack inserted by MCS to empty structures */
continue;
}
return mono_class_inflate_generic_method_full (gklass->vtable [offset], class, mono_class_get_context (class));
}
+ if (class->rank == 1) {
+ /*
+ * szarrays do not overwrite any methods of Array, so we can avoid
+ * initializing their vtables in some cases.
+ */
+ mono_class_setup_vtable (class->parent);
+ if (offset < class->parent->vtable_size)
+ return class->parent->vtable [offset];
+ }
+
mono_class_setup_vtable (class);
return class->vtable [offset];
}
if (class->generic_class) {
MonoClass *gklass = class->generic_class->container_class;
- class->property = gklass->property;
-
mono_class_init (gklass);
mono_class_setup_properties (gklass);
+ class->property = gklass->property;
+
properties = g_new0 (MonoProperty, class->property.count + 1);
for (i = 0; i < class->property.count; i++) {
}
}
+static MonoClass*
+inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
+{
+ MonoType *args [1];
+ args [0] = &arg0->byval_arg;
+
+ return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
+}
+
+static MonoClass*
+array_class_get_if_rank (MonoClass *class, guint rank)
+{
+ return rank ? mono_array_class_get (class, rank) : class;
+}
+
+static void
+fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
+{
+ valuetype_types [0] = eclass;
+ if (eclass == mono_defaults.int16_class)
+ valuetype_types [1] = mono_defaults.uint16_class;
+ else if (eclass == mono_defaults.uint16_class)
+ valuetype_types [1] = mono_defaults.int16_class;
+ else if (eclass == mono_defaults.int32_class)
+ valuetype_types [1] = mono_defaults.uint32_class;
+ else if (eclass == mono_defaults.uint32_class)
+ valuetype_types [1] = mono_defaults.int32_class;
+ else if (eclass == mono_defaults.int64_class)
+ valuetype_types [1] = mono_defaults.uint64_class;
+ else if (eclass == mono_defaults.uint64_class)
+ valuetype_types [1] = mono_defaults.int64_class;
+ else if (eclass == mono_defaults.byte_class)
+ valuetype_types [1] = mono_defaults.sbyte_class;
+ else if (eclass == mono_defaults.sbyte_class)
+ valuetype_types [1] = mono_defaults.byte_class;
+ else if (eclass->enumtype && eclass->enum_basetype)
+ valuetype_types [1] = mono_class_from_mono_type (eclass->enum_basetype);
+}
+
/* this won't be needed once bug #325495 is completely fixed
* though we'll need something similar to know which interfaces to allow
* in arrays when they'll be lazyly created
+ *
+ * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
+ * MS returns diferrent types based on which instance is called. For example:
+ * object obj = new byte[10][];
+ * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
+ * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
+ * a != b ==> true
+ *
+ * Fixing this should kill quite some code, save some bits and improve compatbility.
*/
static MonoClass**
get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
static MonoClass* generic_icollection_class = NULL;
static MonoClass* generic_ienumerable_class = NULL;
static MonoClass* generic_ienumerator_class = NULL;
- MonoClass *fclass = NULL;
+ MonoClass *valuetype_types[2] = { NULL, NULL };
MonoClass **interfaces = NULL;
- int i, interface_count, real_count;
+ int i, interface_count, real_count, original_rank;
int all_interfaces;
gboolean internal_enumerator;
gboolean eclass_is_valuetype;
}
internal_enumerator = FALSE;
eclass_is_valuetype = FALSE;
+ original_rank = eclass->rank;
if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
/*
* For a Enumerator<T[]> we need to get the list of interfaces for T.
*/
eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
+ original_rank = eclass->rank;
eclass = eclass->element_class;
internal_enumerator = TRUE;
*is_enumerator = TRUE;
* the generic interfaces needed to implement.
*/
if (eclass->valuetype) {
- if (eclass == mono_defaults.int16_class)
- fclass = mono_defaults.uint16_class;
- else if (eclass == mono_defaults.uint16_class)
- fclass = mono_defaults.int16_class;
- else if (eclass == mono_defaults.int32_class)
- fclass = mono_defaults.uint32_class;
- else if (eclass == mono_defaults.uint32_class)
- fclass = mono_defaults.int32_class;
- else if (eclass == mono_defaults.int64_class)
- fclass = mono_defaults.uint64_class;
- else if (eclass == mono_defaults.uint64_class)
- fclass = mono_defaults.int64_class;
- else if (eclass == mono_defaults.byte_class)
- fclass = mono_defaults.sbyte_class;
- else if (eclass == mono_defaults.sbyte_class)
- fclass = mono_defaults.byte_class;
- else {
- /* No additional interfaces for other value types */
- *num = 0;
- return NULL;
- }
+ fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
/* IList, ICollection, IEnumerable */
- real_count = interface_count = 3;
- interfaces = g_malloc0 (sizeof (MonoClass*) * interface_count);
- interfaces [0] = fclass;
+ real_count = interface_count = valuetype_types [1] ? 6 : 3;
+ if (internal_enumerator) {
+ ++real_count;
+ if (valuetype_types [1])
+ ++real_count;
+ }
+
+ interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
+ interfaces [0] = valuetype_types [0];
+ if (valuetype_types [1])
+ interfaces [3] = valuetype_types [1];
+
eclass_is_valuetype = TRUE;
} else {
int j;
interface_count++;
else
interface_count += idepth;
+ if (eclass->rank && eclass->element_class->valuetype) {
+ fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
+ if (valuetype_types [1])
+ ++interface_count;
+ }
/* IList, ICollection, IEnumerable */
interface_count *= 3;
real_count = interface_count;
- if (internal_enumerator)
- real_count += idepth + eclass->interface_offsets_count;
+ if (internal_enumerator) {
+ real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
+ if (valuetype_types [1])
+ ++real_count;
+ }
interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
if (MONO_CLASS_IS_INTERFACE (eclass)) {
interfaces [0] = mono_defaults.object_class;
j += 3;
}
}
+ if (valuetype_types [1]) {
+ interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
+ j += 3;
+ }
}
/* instantiate the generic interfaces */
for (i = 0; i < interface_count; i += 3) {
- MonoType *args [1];
MonoClass *iface = interfaces [i];
- args [0] = &iface->byval_arg;
- interfaces [i] = mono_class_bind_generic_parameters (
- mono_defaults.generic_ilist_class, 1, args, FALSE);
- //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));
- args [0] = &iface->byval_arg;
- interfaces [i + 1] = mono_class_bind_generic_parameters (
- generic_icollection_class, 1, args, FALSE);
- args [0] = &iface->byval_arg;
- interfaces [i + 2] = mono_class_bind_generic_parameters (
- generic_ienumerable_class, 1, args, FALSE);
- //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 1]->byval_arg, 0));
- //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 2]->byval_arg, 0));
+ interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
+ interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
+ interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
}
if (internal_enumerator) {
int j;
/* instantiate IEnumerator<iface> */
for (i = 0; i < interface_count; i++) {
- MonoType *args [1];
- MonoClass *iface = interfaces [i];
-
- args [0] = &iface->byval_arg;
- interfaces [i] = mono_class_bind_generic_parameters (
- generic_ienumerator_class, 1, args, FALSE);
- /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+ interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
}
+ j = interface_count;
if (!eclass_is_valuetype) {
- j = interface_count;
- for (i = 0; i < eclass->idepth; i++) {
- MonoType *args [1];
- args [0] = &eclass->supertypes [i]->byval_arg;
- interfaces [j] = mono_class_bind_generic_parameters (
- generic_ienumerator_class, 1, args, FALSE);
- /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+ if (MONO_CLASS_IS_INTERFACE (eclass)) {
+ interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
j ++;
+ } else {
+ for (i = 0; i < eclass->idepth; i++) {
+ interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
+ j ++;
+ }
}
for (i = 0; i < eclass->interface_offsets_count; i++) {
- MonoClass *iface = eclass->interfaces_packed [i];
- MonoType *args [1];
- args [0] = &iface->byval_arg;
- interfaces [j] = mono_class_bind_generic_parameters (
- generic_ienumerator_class, 1, args, FALSE);
- /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+ interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
j ++;
}
+ } else {
+ interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
}
+ if (valuetype_types [1])
+ interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
+ }
+#if 0
+ {
+ char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
+ for (i = 0; i < real_count; ++i) {
+ char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
+ g_print ("%s implements %s\n", type_name, name);
+ g_free (name);
}
+ g_free (type_name);
+ }
+#endif
*num = real_count;
return interfaces;
}
if (class->vtable)
return;
- /* This sets method->slot for all methods if this is an interface */
- mono_class_setup_methods (class);
+ if (mono_debug_using_mono_debugger ())
+ /* The debugger currently depends on this */
+ mono_class_setup_methods (class);
- if (MONO_CLASS_IS_INTERFACE (class))
+ if (MONO_CLASS_IS_INTERFACE (class)) {
+ /* This sets method->slot for all methods if this is an interface */
+ mono_class_setup_methods (class);
return;
+ }
mono_loader_lock ();
#define DEBUG_INTERFACE_VTABLE_CODE 0
#define TRACE_INTERFACE_VTABLE_CODE 0
+#define VERIFY_INTERFACE_VTABLE_CODE 0
#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
#define DEBUG_INTERFACE_VTABLE(stmt) do {\
#define TRACE_INTERFACE_VTABLE(stmt)
#endif
+#if VERIFY_INTERFACE_VTABLE_CODE
+#define VERIFY_INTERFACE_VTABLE(stmt) do {\
+ stmt;\
+} while (0)
+#else
+#define VERIFY_INTERFACE_VTABLE(stmt)
+#endif
+
#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
static char*
}
#endif
+#if VERIFY_INTERFACE_VTABLE_CODE
+static int
+mono_method_try_get_vtable_index (MonoMethod *method)
+{
+ if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
+ MonoMethodInflated *imethod = (MonoMethodInflated*)method;
+ if (imethod->declaring->is_generic)
+ return imethod->declaring->slot;
+ }
+ return method->slot;
+}
+
+static void
+mono_class_verify_vtable (MonoClass *class)
+{
+ int i;
+ char *full_name = mono_type_full_name (&class->byval_arg);
+
+ printf ("*** Verifying VTable of class '%s' \n", full_name);
+ g_free (full_name);
+ full_name = NULL;
+
+ if (!class->methods)
+ return;
+
+ for (i = 0; i < class->method.count; ++i) {
+ MonoMethod *cm = class->methods [i];
+ int slot;
+
+ if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
+ continue;
+
+ g_free (full_name);
+ full_name = mono_method_full_name (cm, TRUE);
+
+ slot = mono_method_try_get_vtable_index (cm);
+ if (slot >= 0) {
+ if (slot >= class->vtable_size) {
+ printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
+ continue;
+ }
+
+ if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot] && class->vtable [slot]->wrapper_type != MONO_WRAPPER_STATIC_RGCTX_INVOKE)) {
+ char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
+ printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
+ g_free (other_name);
+ }
+ } else
+ printf ("\tVirtual method %s does n't have an assigned slot\n", full_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;
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);
+ mono_class_setup_methods (class);
for (index = 0; index < class->method.count; ++index) {
MonoMethod *cm = class->methods [index];
method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
GPtrArray *ifaces = NULL;
GHashTable *override_map = NULL;
gboolean security_enabled = mono_is_security_manager_active ();
+ MonoMethod *cm;
+ gpointer class_iter;
#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
int first_non_interface_slot;
#endif
max_iid = class->max_interface_id;
DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
+ /* Optimized version for generic instances */
+ if (class->generic_class) {
+ MonoClass *gklass = class->generic_class->container_class;
+ gboolean usable = TRUE;
+
+ mono_class_setup_vtable (gklass);
+ for (i = 0; i < gklass->vtable_size; ++i)
+ if (gklass->vtable [i] && gklass->vtable [i]->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
+ usable = FALSE;
+
+ if (usable) {
+ MonoMethod **tmp = mono_image_alloc0 (class->image, sizeof (gpointer) * gklass->vtable_size);
+ class->vtable_size = gklass->vtable_size;
+ for (i = 0; i < gklass->vtable_size; ++i)
+ if (gklass->vtable [i])
+ tmp [i] = mono_class_inflate_generic_method_full (gklass->vtable [i], class, mono_class_get_context (class));
+ mono_memory_barrier ();
+ class->vtable = tmp;
+
+ /* Have to set method->slot for abstract virtual methods */
+ if (class->methods && gklass->methods) {
+ for (i = 0; i < class->method.count; ++i)
+ if (class->methods [i]->slot == -1)
+ class->methods [i]->slot = gklass->methods [i]->slot;
+ }
+
+ return;
+ }
+ }
+
if (class->parent && class->parent->vtable_size) {
MonoClass *parent = class->parent;
int i;
MonoMethod *decl = overrides [i*2];
if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
int dslot;
- g_assert (decl->slot != -1);
dslot = mono_method_get_vtable_slot (decl) + mono_class_interface_offset (class, decl->klass);
vtable [dslot] = overrides [i*2 + 1];
vtable [dslot]->slot = dslot;
// otherwise look for a matching method
if (override_im == NULL) {
int cm_index;
-
+ gpointer iter;
+ MonoMethod *cm;
+
// 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];
-
+ iter = NULL;
+ while ((cm = mono_class_get_virtual_methods (class, &iter))) {
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)) {
+ if (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? */
}
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;
-
- cm = class->methods [i];
-
- /*
- * Non-virtual method have no place in the vtable.
- * This also catches static methods (since they are not virtual).
- */
- if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
- continue;
-
+ class_iter = NULL;
+ while ((cm = mono_class_get_virtual_methods (class, &class_iter))) {
/*
* If the method is REUSE_SLOT, we must check in the
* base class for a method to override.
if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
int slot = -1;
for (k = class->parent; k ; k = k->parent) {
- int j;
- for (j = 0; j < k->method.count; ++j) {
- MonoMethod *m1 = k->methods [j];
- MonoMethodSignature *cmsig, *m1sig;
+ gpointer k_iter;
+ MonoMethod *m1;
- if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
- continue;
+ k_iter = NULL;
+ while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
+ MonoMethodSignature *cmsig, *m1sig;
cmsig = mono_method_signature (cm);
m1sig = mono_method_signature (m1);
if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
check_core_clr_override_method (class, cm, m1);
- slot = k->methods [j]->slot;
+ slot = mono_method_get_vtable_slot (m1);
g_assert (cm->slot < max_vtsize);
if (!override_map)
override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
}
}
}
+
+ VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
}
/*
if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
MonoMethodInflated *imethod = (MonoMethodInflated*)method;
if (imethod->declaring->is_generic)
- return imethod->declaring->slot;
+ return mono_method_get_vtable_slot (imethod->declaring);
}
- return method->slot;
+ return mono_method_get_vtable_slot (method);
}
static MonoMethod *default_ghc = NULL;
/*g_print ("array generic methods: %d\n", count_generic);*/
generic_array_method_num = count_generic;
+ g_list_free (list);
return generic_array_method_num;
}
class->field = gklass->field;
mono_class_init (gklass);
+ // FIXME: Why is this needed ?
mono_class_setup_methods (gklass);
- mono_class_setup_properties (gklass);
if (MONO_CLASS_IS_INTERFACE (class))
class->interface_id = mono_get_unique_iid (class);
if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
if (!strncmp (name, "Vector", 6))
- class->simd_type = !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b");
+ class->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
}
mono_loader_unlock ();
return klass;
}
+/*
+ * LOCKING: Acquires the loader lock.
+ */
MonoClass *
mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
{
/* FIXME: */
image = mono_defaults.corlib;
- klass = param->pklass = mono_image_alloc0 (image, sizeof (MonoClass));
+ klass = mono_image_alloc0 (image, sizeof (MonoClass));
if (param->name)
klass->name = param->name;
mono_class_setup_supertypes (klass);
+ mono_memory_barrier ();
+
+ param->pklass = klass;
+
mono_loader_unlock ();
mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
int i;
for (i = 0; i < class->field.count; ++i)
- if (class->fields [i].name == name)
+ if (mono_field_get_name (&class->fields [i]) == name)
return &class->fields [i];
g_assert_not_reached ();
} else {
mono_class_setup_fields_locking (klass);
while (klass) {
for (i = 0; i < klass->field.count; ++i) {
- if (strcmp (name, klass->fields [i].name) == 0)
+ if (strcmp (name, mono_field_get_name (&klass->fields [i])) == 0)
return &klass->fields [i];
}
klass = klass->parent;
return 0;
}
+static int
+mono_field_get_index (MonoClassField *field)
+{
+ int index = field - field->parent->fields;
+
+ g_assert (index >= 0 && index < field->parent->field.count);
+
+ return index;
+}
+
/*
* mono_class_get_field_default_value:
*
{
guint32 cindex;
guint32 constant_cols [MONO_CONSTANT_SIZE];
+ int field_index;
+ MonoClass *klass = field->parent;
g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
- if (!field->data) {
+ if (!klass->field_def_values) {
+ mono_loader_lock ();
+ if (!klass->field_def_values)
+ klass->field_def_values = mono_image_alloc0 (klass->image, sizeof (MonoFieldDefaultValue) * klass->field.count);
+ mono_loader_unlock ();
+ }
+
+ field_index = mono_field_get_index (field);
+
+ if (!klass->field_def_values [field_index].data) {
cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
g_assert (cindex);
g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
- field->def_type = constant_cols [MONO_CONSTANT_TYPE];
- field->data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
+ klass->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
+ klass->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
}
- *def_type = field->def_type;
- return field->data;
+ *def_type = klass->field_def_values [field_index].def_type;
+ return klass->field_def_values [field_index].data;
}
guint32
return NULL;
if (!*iter) {
mono_class_setup_fields_locking (klass);
+ if (klass->exception_type)
+ return NULL;
/* start from the first */
if (klass->field.count) {
return *iter = &klass->fields [0];
return NULL;
}
+/*
+ * mono_class_get_virtual_methods:
+ *
+ * Iterate over the virtual methods of KLASS.
+ *
+ * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
+ */
+static MonoMethod*
+mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
+{
+ MonoMethod** method;
+ if (!iter)
+ return NULL;
+ if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
+ if (!*iter) {
+ mono_class_setup_methods (klass);
+ /* start from the first */
+ method = &klass->methods [0];
+ } else {
+ method = *iter;
+ method++;
+ }
+ while (method < &klass->methods [klass->method.count]) {
+ if (((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
+ break;
+ method ++;
+ }
+ if (method < &klass->methods [klass->method.count]) {
+ *iter = method;
+ return *method;
+ } else {
+ return NULL;
+ }
+ } else {
+ /* Search directly in metadata to avoid calling setup_methods () */
+ MonoMethod *res = NULL;
+ int i, start_index;
+
+ if (!*iter) {
+ start_index = 0;
+ } else {
+ start_index = GPOINTER_TO_UINT (*iter);
+ }
+
+ for (i = start_index; i < klass->method.count; ++i) {
+ guint32 cols [MONO_METHOD_SIZE];
+
+ /* class->method.first points into the methodptr table */
+ mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
+
+ if (cols [MONO_METHOD_FLAGS] & METHOD_ATTRIBUTE_VIRTUAL)
+ break;
+ }
+
+ if (i < klass->method.count) {
+ res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
+ /* Add 1 here so the if (*iter) check fails */
+ *iter = GUINT_TO_POINTER (i + 1);
+ return res;
+ } else {
+ return NULL;
+ }
+ }
+}
+
/**
* mono_class_get_properties:
* @klass: the MonoClass to act on
return field->offset;
}
+static const char *
+mono_field_get_rva (MonoClassField *field)
+{
+ guint32 rva;
+ int field_index;
+ MonoClass *klass = field->parent;
+
+ g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
+
+ if (!klass->field_def_values) {
+ mono_loader_lock ();
+ if (!klass->field_def_values)
+ klass->field_def_values = mono_image_alloc0 (klass->image, sizeof (MonoFieldDefaultValue) * klass->field.count);
+ mono_loader_unlock ();
+ }
+
+ field_index = mono_field_get_index (field);
+
+ if (!klass->field_def_values [field_index].data && !klass->image->dynamic) {
+ mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
+ if (!rva)
+ g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
+ klass->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
+ }
+
+ return klass->field_def_values [field_index].data;
+}
+
/**
* mono_field_get_data;
* @field: the MonoClassField to act on
* data if it has an RVA flag.
*/
const char *
-mono_field_get_data (MonoClassField *field)
+mono_field_get_data (MonoClassField *field)
{
- return field->data;
+ if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
+ MonoTypeEnum def_type;
+
+ return mono_class_get_field_default_value (field, &def_type);
+ } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
+ return mono_field_get_rva (field);
+ } else {
+ return NULL;
+ }
}
/**
mono_class_init (klass);
- if (klass->methods || klass->generic_class) {
+ if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
mono_class_setup_methods (klass);
for (i = 0; i < klass->method.count; ++i) {
MonoMethod *method = klass->methods [i];
*
* Visibility checks ignoring generic instantiations.
*/
-static gboolean
+gboolean
mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
{
int i;
gboolean
mono_class_generic_sharing_enabled (MonoClass *class)
{
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__ppc__) || defined(__powerpc__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__mono_ppc__)
static gboolean supported = TRUE;
#else
/* Not supported by the JIT backends */
g_assert_not_reached ();
}
}
+
+/*
+ * mono_class_setup_interface_id:
+ *
+ * Initializes MonoClass::interface_id if required.
+ *
+ * LOCKING: Acquires the loader lock.
+ */
+void
+mono_class_setup_interface_id (MonoClass *class)
+{
+ mono_loader_lock ();
+ if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
+ class->interface_id = mono_get_unique_iid (class);
+ mono_loader_unlock ();
+}