r->byref = original->byref;
if (t->type == MONO_TYPE_PTR)
t->data.type = dup_type (t->data.type, original->data.type);
+ else if (t->type == MONO_TYPE_ARRAY)
+ t->data.array = mono_dup_array_type (t->data.array);
+ else if (t->type == MONO_TYPE_FNPTR)
+ t->data.method = mono_metadata_signature_deep_dup (t->data.method);
mono_stats.generics_metadata_size += sizeof (MonoType);
return r;
}
+/* Copy everything mono_metadata_free_array free. */
+MonoArrayType *
+mono_dup_array_type (MonoArrayType *a)
+{
+ a = g_memdup (a, sizeof (MonoArrayType));
+ if (a->sizes)
+ a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
+ if (a->lobounds)
+ a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
+ return a;
+}
+
+/* Copy everything mono_metadata_free_method_signature free. */
+MonoMethodSignature*
+mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
+{
+ int i;
+
+ sig = mono_metadata_signature_dup (sig);
+
+ sig->ret = dup_type (sig->ret, sig->ret);
+ for (i = 0; i < sig->param_count; ++i)
+ sig->params [i] = dup_type (sig->params [i], sig->params [i]);
+
+ return sig;
+}
+
static void
_mono_type_get_assembly_name (MonoClass *klass, GString *str)
{
_mono_type_get_assembly_name (type->data.klass, str);
break;
}
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ g_assert (type->data.generic_param->name);
+ g_string_append (str, type->data.generic_param->name);
+ break;
default:
klass = mono_class_from_mono_type (type);
if (klass->nested_in) {
/**
* mono_type_get_name:
* @type: a type
+ * @format: the format for the return string.
*
- * Returns: the string representation for type as required by System.Reflection.
- * The inverse of mono_reflection_parse_type ().
+ *
+ * Returns: the string representation in a number of formats:
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
+ * returned in the formatrequired by System.Reflection, this is the
+ * inverse of mono_reflection_parse_type ().
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
+ * be used by the IL assembler.
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
+ *
+ * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
*/
char*
mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
{
GString* result;
- if (format == MONO_TYPE_NAME_FORMAT_FULL_NAME &&
- ((type->type == MONO_TYPE_VAR) || (type->type == MONO_TYPE_MVAR) ||
- ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->inst->is_open)))
- return NULL;
-
result = g_string_new ("");
mono_type_get_name_recurse (type, result, FALSE, format);
return g_string_free (result, FALSE);
}
+/**
+ * mono_type_get_full_name:
+ * @class: a class
+ *
+ * Returns: the string representation for type as required by System.Reflection.
+ * The inverse of mono_reflection_parse_type ().
+ */
+char *
+mono_type_get_full_name (MonoClass *class)
+{
+ return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
+}
+
char*
mono_type_get_name (MonoType *type)
{
igclass->klass = NULL;
ngclass->context = g_new0 (MonoGenericContext, 1);
- ngclass->context->container = context->container;
+ ngclass->context->container = ngclass->container_class->generic_container;
ngclass->context->gclass = ngclass;
mono_loader_lock ();
} else
res->gmethod = inflate_with->gmethod;
+ if (res->gmethod) {
+ res->gmethod->container->parent = res->container;
+ res->container = res->gmethod->container;
+ }
+
return res;
}
+/**
+ * mono_class_inflate_generic_method:
+ *
+ * Instantiate method @method with the generic context @context.
+ */
MonoMethod*
mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
{
MonoMethodInflated *result;
+ MonoGenericContainer *container = context ? context->container : NULL;
+ MonoMethodSignature *sig;
- if (method->is_inflated || mono_method_signature_full (method, context)->is_inflated) {
+ /* The `method' has already been instantiated before -> we need to create a new context. */
+ sig = mono_method_signature_full (method, container);
+ if (method->is_inflated || sig->is_inflated) {
MonoMethodInflated *imethod = (MonoMethodInflated *) method;
context = inflate_generic_context (imethod->context, context);
mono_stats.inflated_method_count++;
+ /* Just create a copy, but don't actually inflate the method for performance reasons. */
result = g_new0 (MonoMethodInflated, 1);
- result->nmethod = *(MonoMethodNormal*)method;
- result->nmethod.method.is_inflated = 1;
+ if (sig->pinvoke)
+ result->method.pinvoke = *(MonoMethodPInvoke*)method;
+ else
+ result->method.normal = *(MonoMethodNormal*)method;
+ result->method.method.is_inflated = 1;
result->context = context;
result->declaring = method;
- if (result->nmethod.method.klass->generic_class)
- result->nmethod.method.klass = result->nmethod.method.klass->generic_class->container_class;
+ if (result->method.method.klass->generic_class)
+ result->method.method.klass = result->method.method.klass->generic_class->container_class;
return (MonoMethod *) result;
}
+/**
+ * mono_get_inflated_method:
+ *
+ * For performance reasons, mono_class_inflate_generic_method() does not actually instantiate the
+ * method, it just "prepares" it for that. If you really need to fully instantiate the method
+ * (including its signature and header), call this method.
+ */
MonoMethod *
mono_get_inflated_method (MonoMethod *method)
{
mh = mono_method_get_header (method);
if (mh)
- res->nmethod.header = inflate_generic_header (mh, imethod->context);
+ res->method.normal.header = inflate_generic_header (mh, imethod->context);
dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
- rklass = res->nmethod.method.klass = mono_class_from_mono_type (dtype);
+ rklass = res->method.method.klass = mono_class_from_mono_type (dtype);
- res->nmethod.method.signature = mono_class_inflate_generic_signature (
+ res->method.method.signature = mono_class_inflate_generic_signature (
method->klass->image, mono_method_signature (method), imethod->context);
return (MonoMethod *) res;
}
+/**
+ * mono_class_find_enum_basetype:
+ * @class: The enum class
+ *
+ * Determine the basetype of an enum by iterating through its fields. We do this
+ * in a separate function since it is cheaper than calling mono_class_setup_fields.
+ */
+static MonoType*
+mono_class_find_enum_basetype (MonoClass *class)
+{
+ MonoImage *m = class->image;
+ const int top = class->field.count;
+ MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
+ int i;
+
+ g_assert (class->enumtype);
+
+ /*
+ * Fetch all the field information.
+ */
+ for (i = 0; i < top; i++){
+ const char *sig;
+ guint32 cols [MONO_FIELD_SIZE];
+ int idx = class->field.first + i;
+ MonoGenericContainer *container = NULL;
+ MonoType *ftype;
+
+ mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
+ sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
+ mono_metadata_decode_value (sig, &sig);
+ /* FIELD signature == 0x06 */
+ g_assert (*sig == 0x06);
+ if (class->generic_container)
+ container = class->generic_container;
+ else if (class->generic_class) {
+ MonoClass *gklass = class->generic_class->container_class;
+
+ container = gklass->generic_container;
+ g_assert (container);
+ }
+ ftype = mono_metadata_parse_type_full (
+ m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
+ cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ if (class->generic_class) {
+ ftype = mono_class_inflate_generic_type (
+ ftype, class->generic_class->context);
+ ftype->attrs = cols [MONO_FIELD_FLAGS];
+ }
+
+ if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
+ return ftype;
+ }
+
+ return NULL;
+}
+
/**
* mono_class_setup_fields:
- * @m: pointer to the metadata.
* @class: The class to initialize
*
* Initializes the class->fields.
+ * Assumes the loader lock is held.
*/
static void
mono_class_setup_fields (MonoClass *class)
if (class->size_inited)
return;
+ if (class->inited)
+ mono_class_init (class);
+
class->instance_size = 0;
class->class_size = 0;
/* Prevent infinite loops if the class references itself */
class->size_inited = 1;
- class->fields = g_new0 (MonoClassField, top);
+ class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
/*
* Fetch all the field information.
mono_class_layout_fields (class);
}
+/**
+ * mono_class_setup_fields_locking:
+ * @class: The class to initialize
+ *
+ * Initializes the class->fields.
+ * Aquires the loader lock.
+ */
+static void
+mono_class_setup_fields_locking (MonoClass *class)
+{
+ mono_loader_lock ();
+ mono_class_setup_fields (class);
+ mono_loader_unlock ();
+}
+
+/*
+ * mono_class_has_references:
+ *
+ * Returns whenever @klass->has_references is set, initializing it if needed.
+ * Aquires the loader lock.
+ */
+static gboolean
+mono_class_has_references (MonoClass *klass)
+{
+ if (klass->init_pending) {
+ /* Be conservative */
+ return TRUE;
+ } else {
+ mono_class_init (klass);
+
+ return klass->has_references;
+ }
+}
+
/* useful until we keep track of gc-references in corlib etc. */
#define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
gc_aware_layout = TRUE;
}
+ /* Compute klass->has_references */
+ /*
+ * Process non-static fields first, since static fields might recursively
+ * refer to the class itself.
+ */
+ for (i = 0; i < top; i++) {
+ MonoType *ftype;
+
+ field = &class->fields [i];
+
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+ ftype = mono_type_get_underlying_type (field->type);
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ class->has_references = TRUE;
+ }
+ }
+
+ for (i = 0; i < top; i++) {
+ MonoType *ftype;
+
+ field = &class->fields [i];
+
+ if (!field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+ ftype = mono_type_get_underlying_type (field->type);
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ class->has_static_refs = TRUE;
+ }
+ }
+
for (i = 0; i < top; i++) {
MonoType *ftype;
field = &class->fields [i];
ftype = mono_type_get_underlying_type (field->type);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_from_mono_type (ftype)->has_references))) {
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
class->has_static_refs = TRUE;
else
int i;
MonoMethod **methods;
- if (class->methods || class->generic_class)
+ if (class->methods)
return;
mono_loader_lock ();
//printf ("INIT: %s.%s\n", class->name_space, class->name);
- if (!class->generic_class && !class->methods) {
- methods = g_new (MonoMethod*, class->method.count);
+ if (!class->methods) {
+ methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
for (i = 0; i < class->method.count; ++i) {
- methods [i] = mono_get_method (class->image,
- MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
+ methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
}
}
for (i = 0; i < class->method.count; ++i)
methods [i]->slot = i;
+ /* Leave this assignment as the last op in this function */
class->methods = methods;
mono_loader_unlock ();
MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
MonoProperty *properties;
+ guint32 last;
if (class->properties)
return;
return;
}
- class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
- class->property.count = class->property.last - class->property.first;
+ class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
+ class->property.count = last - class->property.first;
if (class->property.count)
mono_class_setup_methods (class);
- properties = g_new0 (MonoProperty, class->property.count);
- for (i = class->property.first; i < class->property.last; ++i) {
+ properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
+ for (i = class->property.first; i < last; ++i) {
mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
properties [i - class->property.first].parent = class;
properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
}
}
+ /* Leave this assignment as the last op in the function */
class->properties = properties;
mono_loader_unlock ();
guint32 cols [MONO_EVENT_SIZE];
MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
+ guint32 last;
+ MonoEvent *events;
if (class->events)
return;
- class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
- class->event.count = class->event.last - class->event.first;
+ mono_loader_lock ();
+
+ if (class->events) {
+ mono_loader_unlock ();
+ return;
+ }
+ class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
+ class->event.count = last - class->event.first;
if (class->event.count)
mono_class_setup_methods (class);
- class->events = g_new0 (MonoEvent, class->event.count);
- for (i = class->event.first; i < class->event.last; ++i) {
- MonoEvent *event = &class->events [i - class->event.first];
+ events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
+ for (i = class->event.first; i < last; ++i) {
+ MonoEvent *event = &events [i - class->event.first];
mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
event->parent = class;
}
}
}
+ /* Leave this assignment as the last op in the function */
+ class->events = events;
+
+ mono_loader_unlock ();
}
static guint
char *str;
gpointer value;
+ int generic_id;
g_assert (MONO_CLASS_IS_INTERFACE (class));
if (!iid_hash)
iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
- str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
+ if (class->generic_class && !class->generic_class->inst->is_open) {
+ generic_id = class->generic_class->inst->id;
+ g_assert (generic_id != 0);
+ } else
+ generic_id = 0;
+
+ str = g_strdup_printf ("%s|%s.%s|%d", class->image->name, class->name_space, class->name,
+ generic_id);
if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
mono_loader_unlock ();
return cur_slot;
}
+static void
+setup_generic_vtable (MonoClass *class)
+{
+ MonoClass *gklass;
+ int i;
+
+ gklass = class->generic_class->container_class;
+
+ mono_class_init (gklass);
+ class->vtable_size = gklass->vtable_size;
+
+ class->vtable = g_new0 (MonoMethod*, class->vtable_size);
+ memcpy (class->vtable, gklass->vtable, sizeof (MonoMethod*) * class->vtable_size);
+
+ for (i = 0; i < class->vtable_size; i++) {
+ MonoMethod *m = class->vtable [i];
+
+ if (!m)
+ continue;
+
+ m = mono_class_inflate_generic_method (m, class->generic_class->context);
+ class->vtable [i] = m;
+ }
+
+ class->max_interface_id = gklass->max_interface_id;
+ class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
+ memcpy (class->interface_offsets, gklass->interface_offsets,
+ sizeof (gint) * (gklass->max_interface_id + 1));
+}
+
void
mono_class_setup_vtable (MonoClass *class)
{
MonoMethod **overrides;
MonoGenericContext *context;
+ guint32 type_token;
int onum = 0;
if (class->vtable)
return;
}
- if (class->generic_class)
+ if (class->generic_class) {
+ if (class->generic_class->inst->is_open) {
+ setup_generic_vtable (class);
+ mono_loader_unlock ();
+ return;
+ }
+
context = class->generic_class->context;
- else
+ type_token = class->generic_class->container_class->type_token;
+ } else {
context = (MonoGenericContext *) class->generic_container;
+ type_token = class->type_token;
+ }
+
+ if (class->image->dynamic)
+ mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
+ else
+ mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
- overrides = mono_class_get_overrides_full (
- class->image, class->type_token, &onum, context);
mono_class_setup_vtable_general (class, overrides, onum);
g_free (overrides);
mono_loader_unlock ();
}
-static void
-setup_generic_vtable (MonoClass *class, MonoMethod **overrides, int onum)
-{
- MonoClass *gklass;
- int i;
-
- gklass = class->generic_class->container_class;
-
- mono_class_init (gklass);
- class->vtable_size = gklass->vtable_size;
-
- class->vtable = g_new0 (MonoMethod*, class->vtable_size);
- memcpy (class->vtable, gklass->vtable, sizeof (MonoMethod*) * class->vtable_size);
-
- for (i = 0; i < class->vtable_size; i++) {
- MonoMethod *m = class->vtable [i];
-
- if (!m)
- continue;
-
- m = mono_class_inflate_generic_method (m, class->generic_class->context);
- class->vtable [i] = m;
- }
-
- class->max_interface_id = gklass->max_interface_id;
- class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
- memcpy (class->interface_offsets, gklass->interface_offsets,
- sizeof (gint) * (gklass->max_interface_id + 1));
-}
-
/*
* LOCKING: this is supposed to be called with the loader lock held.
*/
MonoClass *k, *ic;
MonoMethod **vtable;
int i, max_vtsize = 0, max_iid, cur_slot = 0;
- GPtrArray *ifaces;
+ GPtrArray *ifaces, *pifaces = NULL;
GHashTable *override_map = NULL;
gboolean security_enabled = mono_is_security_manager_active ();
if (class->vtable)
return;
- if (class->generic_class) {
- setup_generic_vtable (class, overrides, onum);
+ if (class->generic_class && class->generic_class->inst->is_open) {
+ setup_generic_vtable (class);
return;
}
int nifaces = 0;
ifaces = mono_class_get_implemented_interfaces (k);
- if (ifaces)
+ 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;
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 = k->interface_offsets [ic->interface_id];
g_assert (io >= 0);
if (vtable [io + l])
continue;
- if (ic->generic_class) {
- the_cname = mono_type_get_name_full (&ic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
+ if (pic) {
+ the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
cname = the_cname;
} else {
the_cname = NULL;
MonoClass *parent = class->parent;
if ((ic->interface_id <= parent->max_interface_id) &&
- (parent->interface_offsets [ic->interface_id]) &&
+ (parent->interface_offsets [ic->interface_id] != -1) &&
parent->vtable)
vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
}
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), FALSE);
+ msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
printf ("METHOD %s(%s)\n", cm->name, msig);
g_free (msig);
if (cm->slot < 0)
cm->slot = cur_slot++;
- if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && ! mono_method_signature (cm)->generic_param_count)
+ if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
vtable [cm->slot] = cm;
}
MonoClass *gklass = class->generic_class->container_class;
mono_class_init (gklass);
- class->vtable_size = gklass->vtable_size;
- } else
+
+ class->vtable_size = MAX (gklass->vtable_size, cur_slot);
+ } else
class->vtable_size = cur_slot;
class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
}
}
-/*
- * If we inherit a type parameter from an outer class, set its owner to that class.
- */
-static int
-set_generic_param_owner (MonoGenericContainer *container, MonoClass *klass, int pos)
-{
- MonoGenericContainer *gc;
- int i;
-
- if (klass->nested_in)
- pos = set_generic_param_owner (container, klass->nested_in, pos);
-
- if (!klass->generic_container)
- return pos;
-
- gc = klass->generic_container;
- for (i = pos; i < gc->type_argc; i++)
- container->type_params [i].owner = gc;
-
- return pos + gc->type_argc;
-}
-
static MonoGenericInst *
get_shared_inst (MonoGenericContainer *container)
{
return mono_metadata_lookup_generic_inst (nginst);
}
+/*
+ * In preparation for implementing shared code.
+ */
MonoGenericClass *
mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
{
const char *name, *nspace;
guint icount = 0;
MonoClass **interfaces;
+ guint32 field_last, method_last;
mono_loader_lock ();
g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
+ /*
+ * Check whether we're a generic type definition.
+ */
class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
if (class->generic_container) {
class->generic_container->klass = class;
context->gclass = mono_get_shared_generic_class (context->container, FALSE);
}
- if (cols [MONO_TYPEDEF_EXTENDS])
+ if (cols [MONO_TYPEDEF_EXTENDS]) {
parent = mono_class_get_full (
image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+ }
mono_class_setup_parent (class, parent);
mono_class_setup_mono_type (class);
- interfaces = mono_metadata_interfaces_from_typedef_full (image, type_token, &icount, context);
+ if (!class->enumtype) {
+ mono_metadata_interfaces_from_typedef_full (image, type_token, &interfaces, &icount, context);
- class->interfaces = interfaces;
- class->interface_count = icount;
+ class->interfaces = interfaces;
+ class->interface_count = icount;
+ }
if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
class->unicode = 1;
if (tt->rows > tidx){
mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
- class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
- class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
+ field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
+ method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
} else {
- class->field.last = image->tables [MONO_TABLE_FIELD].rows;
- class->method.last = image->tables [MONO_TABLE_METHOD].rows;
+ field_last = image->tables [MONO_TABLE_FIELD].rows;
+ method_last = image->tables [MONO_TABLE_METHOD].rows;
}
if (cols [MONO_TYPEDEF_FIELD_LIST] &&
cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
- class->field.count = class->field.last - class->field.first;
+ class->field.count = field_last - class->field.first;
else
class->field.count = 0;
if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
- class->method.count = class->method.last - class->method.first;
+ class->method.count = method_last - class->method.first;
else
class->method.count = 0;
g_assert (class->field.count == 0);
}
- if (class->enumtype)
- mono_class_setup_fields (class);
+ if (class->enumtype) {
+ class->enum_basetype = mono_class_find_enum_basetype (class);
+ class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
+ }
+
+ /*
+ * If we're a generic type definition, load the constraints.
+ * We must do this after the class has been constructed to make certain recursive scenarios
+ * work.
+ */
+ if (class->generic_container)
+ mono_metadata_load_generic_param_constraints (
+ image, type_token, class->generic_container);
if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
class->nested_in = mono_class_create_from_typedef (image, type_token);
- if (class->nested_in && class->generic_container)
- set_generic_param_owner (class->generic_container, class->nested_in, 0);
-
mono_loader_unlock ();
return class;
}
+/** is klass Nullable<T>? */
+gboolean
+mono_class_is_nullable (MonoClass *klass)
+{
+ return klass->generic_class != NULL &&
+ klass->generic_class->container_class == mono_defaults.generic_nullable_class;
+}
+
+
+/** if klass is T? return T */
+MonoClass*
+mono_class_get_nullable_param (MonoClass *klass)
+{
+ g_assert (mono_class_is_nullable (klass));
+ return mono_class_from_mono_type (klass->generic_class->inst->type_argv [0]);
+}
+
+/*
+ * Create the `MonoClass' for an instantiation of a generic type.
+ * We only do this if we actually need it.
+ */
static void
mono_class_create_generic (MonoInflatedGenericClass *gclass)
{
klass->cast_class = klass->element_class = klass;
+ if (mono_class_is_nullable (klass))
+ klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
+
if (gclass->generic_class.is_dynamic) {
klass->instance_size = gklass->instance_size;
klass->class_size = gklass->class_size;
if (klass->parent)
mono_class_setup_parent (klass, klass->parent);
+
+ if (MONO_CLASS_IS_INTERFACE (klass))
+ setup_interface_offsets (klass, 0);
}
MonoClass *
if (param->pklass)
return param->pklass;
- g_assert (param->owner);
-
klass = g_new0 (MonoClass, 1);
if (param->name)
class->inited = 1;
}
+ class->generic_container = eclass->generic_container;
+
list = g_slist_append (rootlist, class);
g_hash_table_insert (image->array_cache, eclass, list);
static MonoClassField *
mono_class_get_field_idx (MonoClass *class, int idx)
{
- mono_class_setup_fields (class);
+ mono_class_setup_fields_locking (class);
- if (class->field.count){
- if ((idx >= class->field.first) && (idx < class->field.last)){
- return &class->fields [idx - class->field.first];
+ while (class) {
+ if (class->field.count) {
+ if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
+ return &class->fields [idx - class->field.first];
+ }
}
+ class = class->parent;
}
-
- if (!class->parent)
- return NULL;
-
- return mono_class_get_field_idx (class->parent, idx);
+ return NULL;
}
/**
return mono_class_get_field_idx (class, idx - 1);
}
+/**
+ * mono_class_get_field_from_name:
+ * @klass: the class to lookup the field.
+ * @name: the field name
+ *
+ * Search the class @klass and it's parents for a field with the name @name.
+ *
+ * Returns: the MonoClassField pointer of the named field or NULL
+ */
MonoClassField *
mono_class_get_field_from_name (MonoClass *klass, const char *name)
{
int i;
+ mono_class_setup_fields_locking (klass);
while (klass) {
- mono_class_setup_fields (klass);
for (i = 0; i < klass->field.count; ++i) {
if (strcmp (name, klass->fields [i].name) == 0)
return &klass->fields [i];
return NULL;
}
+/**
+ * mono_class_get_field_token:
+ * @field: the field we need the token of
+ *
+ * Get the token of a field. Note that the tokesn is only valid for the image
+ * the field was loaded from. Don't use this function for fields in dynamic types.
+ *
+ * Returns: the token representing the field in the image it was loaded from.
+ */
guint32
mono_class_get_field_token (MonoClassField *field)
{
MonoClass *klass = field->parent;
int i;
+ mono_class_setup_fields_locking (klass);
while (klass) {
- mono_class_setup_fields (klass);
for (i = 0; i < klass->field.count; ++i) {
if (&klass->fields [i] == field)
return mono_metadata_make_token (MONO_TABLE_FIELD, klass->field.first + i + 1);
}
char *
-mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+mono_class_name_from_token (MonoImage *image, guint32 type_token)
{
const char *name, *nspace;
if (image->dynamic)
return NULL;
}
+static char *
+mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
+{
+ if (image->dynamic)
+ return g_strdup_printf ("DynamicAssembly %s", image->name);
+
+ switch (type_token & 0xff000000){
+ case MONO_TOKEN_TYPE_DEF:
+ return mono_stringify_assembly_name (&image->assembly->aname);
+ break;
+ case MONO_TOKEN_TYPE_REF: {
+ MonoAssemblyName aname;
+ guint32 cols [MONO_TYPEREF_SIZE];
+ MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
+ guint32 idx;
+
+ mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
+
+ idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
+ switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
+ case MONO_RESOLTION_SCOPE_MODULE:
+ /* FIXME: */
+ return g_strdup ("");
+ case MONO_RESOLTION_SCOPE_MODULEREF:
+ /* FIXME: */
+ return g_strdup ("");
+ case MONO_RESOLTION_SCOPE_TYPEREF:
+ /* FIXME: */
+ return g_strdup ("");
+ case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
+ mono_assembly_get_assemblyref (image, idx - 1, &aname);
+ return mono_stringify_assembly_name (&aname);
+ default:
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ case MONO_TOKEN_TYPE_SPEC:
+ /* FIXME: */
+ return g_strdup ("");
+ default:
+ g_assert_not_reached ();
+ }
+
+ return NULL;
+}
+
/**
* mono_class_get:
* @image: the image where the class resides
}
if (!class){
- char *name = mono_class_name_from_token (image, type_token, context);
- g_warning ("The class %s could not be loaded, used in %s (token 0x%08x)", name, image->name, type_token);
- g_free (name);
+ char *name = mono_class_name_from_token (image, type_token);
+ char *assembly = mono_assembly_name_from_token (image, type_token);
+ mono_loader_set_error_type_load (name, assembly);
}
return class;
if (!oklass->inited)
mono_class_init (oklass);
- if (klass->generic_class)
- klass = klass->generic_class->container_class;
- if (oklass->generic_class)
- oklass = oklass->generic_class->container_class;
-
if (MONO_CLASS_IS_INTERFACE (klass)) {
if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
return FALSE;
if (klass == mono_defaults.object_class)
return TRUE;
- /*
- * Custom version of mono_class_has_parent (oklass, klass)
- */
- if (oklass->idepth >= klass->idepth) {
- MonoClass *parent = oklass->supertypes [klass->idepth - 1];
-
- if (parent->generic_class)
- parent = parent->generic_class->container_class;
-
- return klass == parent;
- }
-
- return FALSE;
+ return mono_class_has_parent (oklass, klass);
}
/*
if (handle_class)
*handle_class = mono_defaults.typehandle_class;
class = mono_class_get_full (image, token, context);
+ if (!class)
+ return NULL;
mono_class_init (class);
/* We return a MonoType* as handle */
return &class->byval_arg;
if (handle_class)
*handle_class = mono_defaults.typehandle_class;
class = mono_class_create_from_typespec (image, token, context);
+ if (!class)
+ return NULL;
mono_class_init (class);
return &class->byval_arg;
}
case MONO_TOKEN_FIELD_DEF: {
MonoClass *class;
guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
- class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
- mono_class_init (class);
if (handle_class)
*handle_class = mono_defaults.fieldhandle_class;
+ class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
+ if (!class)
+ return NULL;
+ mono_class_init (class);
return mono_class_get_field (class, token);
}
case MONO_TOKEN_METHOD_DEF: {
MonoClassField* field;
if (!iter)
return NULL;
- if (!klass->inited)
- mono_class_init (klass);
+ mono_class_setup_fields_locking (klass);
if (!*iter) {
- mono_class_setup_fields (klass);
/* start from the first */
if (klass->field.count) {
return *iter = &klass->fields [0];
MonoDomain *domain = mono_domain_get ();
MonoSecurityManager* secman = mono_security_manager_get_methods ();
MonoMethod *method = klass->exception_data;
- guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_CLASS : MONO_METADATA_INHERITANCEDEMAND_METHOD;
+ guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
MonoObject *exc = NULL;
gpointer args [4];