* Author:
* Miguel de Icaza (miguel@ximian.com)
*
- * (C) 2001 Ximian, Inc.
+ * (C) 2001-2006 Novell, Inc.
*
- * Possible Optimizations:
- * in mono_class_create, do not allocate the class right away,
- * but wait until you know the size of the FieldMap, so that
- * the class embeds directly the FieldMap after the vtable.
- *
- *
*/
#include <config.h>
#include <glib.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/reflection.h>
-#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/exception.h>
#include <mono/metadata/security-manager.h>
#include <mono/os/gc_wrapper.h>
+#include <mono/utils/mono-counters.h>
MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
+/* Function supplied by the runtime to find classes by name using information from the AOT file */
+static MonoGetClassFromName get_class_from_name = NULL;
+
static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
static void mono_class_create_generic (MonoInflatedGenericClass *gclass);
static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
+/*
+ * mono_class_from_typeref:
+ * @image: a MonoImage
+ * @type_token: a TypeRef token
+ *
+ * Creates the MonoClass* structure representing the type defined by
+ * the typeref token valid inside @image.
+ * Returns: the MonoClass* representing the typeref token, NULL ifcould
+ * not be loaded.
+ */
MonoClass *
mono_class_from_typeref (MonoImage *image, guint32 type_token)
{
/* a typedef in disguise */
return mono_class_from_name (image, nspace, name);
case MONO_RESOLTION_SCOPE_MODULEREF:
- return mono_class_from_name (image->modules [idx - 1], nspace, name);
+ if (image->modules [idx-1])
+ return mono_class_from_name (image->modules [idx - 1], nspace, name);
+ else {
+ char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
+ char *human_name;
+
+ human_name = mono_stringify_assembly_name (&image->assembly->aname);
+ mono_loader_set_error_type_load (msg, human_name);
+ g_free (msg);
+ g_free (human_name);
+
+ return NULL;
+ }
case MONO_RESOLTION_SCOPE_TYPEREF: {
MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
GList *tmp;
}
references = image->references;
- if (!references [idx-1])
+ if (!references [idx - 1])
mono_assembly_load_reference (image, idx - 1);
- if (references [idx - 1] == (gpointer)-1)
- return NULL;
+ /* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
+ g_assert (references == image->references);
+ g_assert (references [idx - 1]);
- image = references [idx-1]->image;
+ /* If the assembly did not load, register this as a type load exception */
+ if (references [idx - 1] == REFERENCE_MISSING){
+ MonoAssemblyName aname;
+ char *human_name;
+
+ mono_assembly_get_assemblyref (image, idx - 1, &aname);
+ human_name = mono_stringify_assembly_name (&aname);
+ mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
+ g_free (human_name);
+
+ return NULL;
+ }
- return mono_class_from_name (image, nspace, name);
+ return mono_class_from_name (references [idx - 1]->image, nspace, name);
}
static inline MonoType*
mono_type_get_name_recurse (
&type->data.array->eklass->byval_arg, str, FALSE, nested_format);
g_string_append_c (str, '[');
+ if (rank == 1)
+ g_string_append_c (str, '*');
for (i = 1; i < rank; i++)
g_string_append_c (str, ',');
g_string_append_c (str, ']');
{
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 mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
}
+/**
+ * mono_type_get_name:
+ * @type: a type
+ *
+ * Returns: the string representation for type as it would be represented in IL code.
+ */
char*
mono_type_get_name (MonoType *type)
{
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
}
+/*
+ * mono_type_get_underlying_type:
+ * @type: a type
+ *
+ * Returns: the MonoType for the underlying interger type if @type
+ * is an enum, otherwise the type itself.
+ */
MonoType*
mono_type_get_underlying_type (MonoType *type)
{
- switch (type->type) {
- case MONO_TYPE_VALUETYPE:
- if (type->data.klass->enumtype)
- return type->data.klass->enum_basetype;
- break;
- case MONO_TYPE_GENERICINST:
- return mono_type_get_underlying_type (&type->data.generic_class->container_class->byval_arg);
- default:
- break;
- }
-
+ if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
+ return type->data.klass->enum_basetype;
return type;
}
+/*
+ * mono_class_is_open_constructed_type:
+ * @type: a type
+ *
+ * Returns TRUE if type represents a generics open constructed type
+ * (not all the type parameters required for the instantiation have
+ * been provided).
+ */
gboolean
mono_class_is_open_constructed_type (MonoType *t)
{
{
MonoInflatedGenericClass *igclass;
MonoGenericClass *ngclass, *cached;
+ MonoGenericInst *ninst;
+
+ ninst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
+ if (ninst == ogclass->inst)
+ return ogclass;
if (ogclass->is_dynamic) {
MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
*ngclass = *ogclass;
- ngclass->inst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
+ ngclass->inst = ninst;
igclass->klass = NULL;
inflate_generic_type (MonoType *type, MonoGenericContext *context)
{
switch (type->type) {
- case MONO_TYPE_MVAR:
- if (context->gmethod && context->gmethod->inst->type_argv)
- return dup_type (
- context->gmethod->inst->type_argv [type->data.generic_param->num],
- type);
- else
+ case MONO_TYPE_MVAR: {
+ int num = type->data.generic_param->num;
+ MonoGenericInst *inst = context->gmethod ? context->gmethod->inst : NULL;
+ if (!inst || !inst->type_argv)
return NULL;
- case MONO_TYPE_VAR:
- if (context->gclass)
- return dup_type (
- context->gclass->inst->type_argv [type->data.generic_param->num],
- type);
- else
+ if (num >= inst->type_argc)
+ g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
+ return dup_type (inst->type_argv [num], type);
+ }
+ case MONO_TYPE_VAR: {
+ int num = type->data.generic_param->num;
+ MonoGenericInst *inst = context->gclass ? context->gclass->inst : NULL;
+ if (!inst)
return NULL;
+ if (num >= inst->type_argc)
+ g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
+ return dup_type (inst->type_argv [num], type);
+ }
case MONO_TYPE_SZARRAY: {
MonoClass *eclass = type->data.klass;
MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
return nt;
}
case MONO_TYPE_GENERICINST: {
- MonoGenericClass *ngclass = inflate_generic_class (type->data.generic_class, context);
- MonoType *nt = dup_type (type, type);
- nt->data.generic_class = ngclass;
+ MonoGenericClass *gclass = type->data.generic_class;
+ MonoType *nt;
+ if (!gclass->inst->is_open)
+ return NULL;
+ gclass = inflate_generic_class (gclass, context);
+ if (gclass == type->data.generic_class)
+ return NULL;
+ nt = dup_type (type, type);
+ nt->data.generic_class = gclass;
return nt;
}
case MONO_TYPE_CLASS:
if (!klass->generic_container)
return NULL;
-
gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
-
+ if (gclass == klass->generic_container->context.gclass)
+ return NULL;
nt = dup_type (type, type);
nt->type = MONO_TYPE_GENERICINST;
nt->data.generic_class = gclass;
return (MonoInflatedGenericClass *) gclass;
}
+/*
+ * mono_class_inflate_generic_type:
+ * @type: a type
+ * @context: a generics context
+ *
+ * Instantiate the generic type @type, using the generics context @context.
+ *
+ * Returns: the instantiated type
+ */
MonoType*
mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
{
return inflated;
}
-MonoMethodSignature*
-mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context)
-{
- MonoMethodSignature *res;
- gboolean is_open;
- int i;
-
- if (!context)
- return sig;
-
- res = mono_metadata_signature_alloc (image, sig->param_count);
- res->ret = mono_class_inflate_generic_type (sig->ret, context);
- is_open = mono_class_is_open_constructed_type (res->ret);
- for (i = 0; i < sig->param_count; ++i) {
- res->params [i] = mono_class_inflate_generic_type (sig->params [i], context);
- if (!is_open)
- is_open = mono_class_is_open_constructed_type (res->params [i]);
- }
- res->hasthis = sig->hasthis;
- res->explicit_this = sig->explicit_this;
- res->call_convention = sig->call_convention;
- res->pinvoke = sig->pinvoke;
- res->generic_param_count = sig->generic_param_count;
- res->sentinelpos = sig->sentinelpos;
- res->has_type_parameters = is_open;
- res->is_inflated = 1;
- return res;
-}
-
-static MonoMethodHeader*
-inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
-{
- MonoMethodHeader *res;
- int i;
- res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
- res->code = header->code;
- res->code_size = header->code_size;
- res->max_stack = header->max_stack;
- res->num_clauses = header->num_clauses;
- res->init_locals = header->init_locals;
- res->num_locals = header->num_locals;
- res->clauses = header->clauses;
- for (i = 0; i < header->num_locals; ++i)
- res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
- return res;
-}
-
static MonoGenericContext *
inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
{
- MonoGenericContext *res = g_new0 (MonoGenericContext, 1);
-
- res->container = context->container;
+ MonoGenericClass *gclass = NULL;
+ MonoGenericMethod *gmethod = NULL;
+ MonoGenericContext *res;
if (context->gclass)
- res->gclass = inflate_generic_class (context->gclass, inflate_with);
+ gclass = inflate_generic_class (context->gclass, inflate_with);
if (context->gmethod) {
- res->gmethod = g_new0 (MonoGenericMethod, 1);
- res->gmethod->generic_class = res->gclass;
+ MonoGenericInst *ninst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
+ if (gclass == context->gclass && ninst == context->gmethod->inst) {
+ gmethod = context->gmethod;
+ } else {
+ gmethod = g_new0 (MonoGenericMethod, 1);
+ gmethod->generic_class = gclass;
+ gmethod->container = context->container;
+ gmethod->inst = ninst;
+ }
+ }
- res->gmethod->container = context->gmethod->container;
- res->gmethod->inst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
- } else
- res->gmethod = inflate_with->gmethod;
+ if (gclass == context->gclass && gmethod == context->gmethod)
+ return context;
- if (res->gmethod) {
- res->gmethod->container->parent = res->container;
- res->container = res->gmethod->container;
- }
+ res = g_new0 (MonoGenericContext, 1);
+
+ res->container = gmethod ? gmethod->container : context->container;
+ res->gclass = gclass;
+ res->gmethod = gmethod;
return res;
}
+/*
+ * mono_class_inflate_generic_method:
+ * @method: a generic method
+ * @context: a generics context
+ *
+ * Instantiate the generic method @method using the generics context @context.
+ *
+ * Returns: the new instantiated method
+ */
+MonoMethod *
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
+{
+ return mono_class_inflate_generic_method_full (method, NULL, context);
+}
+
/**
* mono_class_inflate_generic_method:
*
* Instantiate method @method with the generic context @context.
+ * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
+ * Use mono_get_inflated_method (), mono_method_signature () and mono_method_get_header () to get the correct values.
*/
MonoMethod*
-mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
+mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
{
- MonoMethodInflated *result;
- MonoGenericContainer *container = context ? context->container : NULL;
+ MonoMethod *result;
+ MonoMethodInflated *iresult;
MonoMethodSignature *sig;
/* 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) {
+ while (method->is_inflated) {
MonoMethodInflated *imethod = (MonoMethodInflated *) method;
-
context = inflate_generic_context (imethod->context, context);
+ if (context == imethod->context)
+ return method;
method = imethod->declaring;
}
+ if (!method->generic_container && !method->klass->generic_container)
+ return method;
+
mono_stats.inflated_method_count++;
+ iresult = g_new0 (MonoMethodInflated, 1);
- /* Just create a copy, but don't actually inflate the method for performance reasons. */
- result = g_new0 (MonoMethodInflated, 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;
+ sig = mono_method_signature (method);
+ if (sig->pinvoke) {
+ iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
+ } else {
+ iresult->method.normal = *(MonoMethodNormal*)method;
+ iresult->method.normal.header = NULL;
+ }
- if (result->method.method.klass->generic_class)
- result->method.method.klass = result->method.method.klass->generic_class->container_class;
+ result = (MonoMethod *) iresult;
+ result->is_inflated = 1;
+ result->signature = NULL;
+ iresult->context = context;
+ iresult->declaring = method;
+
+ if (!klass_hint || !klass_hint->generic_class ||
+ klass_hint->generic_class->container_class != method->klass ||
+ klass_hint->generic_class->inst != context->gclass->inst)
+ klass_hint = NULL;
+
+ if (method->klass->generic_container)
+ result->klass = klass_hint;
+
+ if (!result->klass) {
+ MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
+ result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
+ }
- return (MonoMethod *) result;
+ if (method->generic_container && !context->gmethod) {
+ MonoGenericMethod *gmethod = g_memdup (method->generic_container->context.gmethod, sizeof (*gmethod));
+ gmethod->generic_class = result->klass->generic_class;
+
+ context = g_new0 (MonoGenericContext, 1);
+ context->container = method->generic_container;
+ context->gclass = result->klass->generic_class;
+ context->gmethod = gmethod;
+
+ iresult->context = context;
+ }
+
+ return result;
}
/**
* 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.
+ * FIXME: Martin? this description looks completely wrong.
*/
MonoMethod *
mono_get_inflated_method (MonoMethod *method)
{
- MonoMethodInflated *imethod, *res;
- MonoMethodHeader *mh;
- MonoType *dtype;
- MonoClass *rklass;
-
- if (!method->is_inflated)
- return method;
-
- imethod = (MonoMethodInflated *) method;
- if (imethod->inflated)
- return (MonoMethod *) imethod->inflated;
-
- mono_stats.inflated_method_count_2++;
- mono_stats.generics_metadata_size +=
- sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
-
- res = g_new0 (MonoMethodInflated, 1);
- *res = *imethod;
- res->inflated = imethod->inflated = res;
-
- mh = mono_method_get_header (method);
- if (mh)
- res->method.normal.header = inflate_generic_header (mh, imethod->context);
-
- dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
- rklass = res->method.method.klass = mono_class_from_mono_type (dtype);
-
- res->method.method.signature = mono_class_inflate_generic_signature (
- method->klass->image, mono_method_signature (method), imethod->context);
-
- return (MonoMethod *) res;
+ return method;
}
/**
{
MonoImage *m = class->image;
const int top = class->field.count;
- MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
int i;
g_assert (class->enumtype);
MonoGenericContainer *container = NULL;
MonoType *ftype;
- mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
+ mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx, cols, MONO_FIELD_SIZE);
sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
mono_metadata_decode_value (sig, &sig);
/* FIELD signature == 0x06 */
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);
+ ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ if (!ftype)
+ return NULL;
if (class->generic_class) {
- ftype = mono_class_inflate_generic_type (
- ftype, class->generic_class->context);
+ ftype = mono_class_inflate_generic_type (ftype, class->generic_class->context);
ftype->attrs = cols [MONO_FIELD_FLAGS];
}
* @class: The class to initialize
*
* Initializes the class->fields.
- * Assumes the loader lock is held.
+ * LOCKING: Assumes the loader lock is held.
*/
static void
mono_class_setup_fields (MonoClass *class)
{
MonoImage *m = class->image;
- const int top = class->field.count;
+ int top = class->field.count;
guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
- MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
- int i, blittable = TRUE, real_size = 0;
- guint32 rva;
+ int i, blittable = TRUE;
+ guint32 real_size = 0;
guint32 packing_size = 0;
gboolean explicit_size;
MonoClassField *field;
+ MonoGenericContainer *container = NULL;
+ MonoClass *gklass = NULL;
if (class->size_inited)
return;
- if (class->inited)
- mono_class_init (class);
+ if (class->generic_class) {
+ MonoClass *gklass = class->generic_class->container_class;
+ mono_class_setup_fields (gklass);
+ top = gklass->field.count;
+ }
class->instance_size = 0;
- class->class_size = 0;
+ if (!class->rank)
+ class->sizes.class_size = 0;
if (class->parent) {
+ /* For generic instances, class->parent might not have been initialized */
+ mono_class_init (class->parent);
if (!class->parent->size_inited)
mono_class_setup_fields (class->parent);
class->instance_size += class->parent->instance_size;
class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
+ if (class->generic_container) {
+ container = class->generic_container;
+ } else if (class->generic_class) {
+ gklass = class->generic_class->container_class;
+ container = gklass->generic_container;
+ g_assert (container);
+
+ mono_class_setup_fields (gklass);
+ }
+
/*
* 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;
-
field = &class->fields [i];
- mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
- /* The name is needed for fieldrefs */
- field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
- 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) {
- MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
- MonoClass *gklass = class->generic_class->container_class;
- container = gklass->generic_container;
- g_assert (container);
+ field->parent = class;
- ifield->generic_type = gklass->fields [i].type;
- field->generic_info = ifield;
- }
- field->type = mono_metadata_parse_type_full (
- m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
- cols [MONO_FIELD_FLAGS], sig + 1, &sig);
- if (mono_field_is_deleted (field))
- continue;
if (class->generic_class) {
- field->type = mono_class_inflate_generic_type (
- field->type, class->generic_class->context);
- field->type->attrs = cols [MONO_FIELD_FLAGS];
- }
+ MonoClassField *gfield = &gklass->fields [i];
+ MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
- field->parent = class;
+ ifield->generic_type = gfield->type;
+ field->name = gfield->name;
+ field->generic_info = ifield;
+ field->type = mono_class_inflate_generic_type (gfield->type, class->generic_class->context);
+ 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];
+
+ mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx, cols, MONO_FIELD_SIZE);
+ /* The name is needed for fieldrefs */
+ field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
+ sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
+ mono_metadata_decode_value (sig, &sig);
+ /* FIELD signature == 0x06 */
+ g_assert (*sig == 0x06);
+ field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ if (!field->type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ break;
+ }
+ if (mono_field_is_deleted (field))
+ continue;
+ if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
+ guint32 offset;
+ mono_metadata_field_info (m, idx, &offset, NULL, NULL);
+ 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);
+ }
+ }
/* Only do these checks if we still think this type is blittable */
if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
}
}
- if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
- mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
- 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 (cols [MONO_FIELD_FLAGS] & 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);
- }
-
- if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
+ if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
class->enum_basetype = field->type;
class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
blittable = class->element_class->blittable;
class->instance_size = MAX (real_size, class->instance_size);
}
+ if (class->exception_type)
+ return;
mono_class_layout_fields (class);
}
* mono_class_setup_fields_locking:
* @class: The class to initialize
*
- * Initializes the class->fields.
+ * Initializes the class->fields array of fields.
* Aquires the loader lock.
*/
static void
}
/* useful until we keep track of gc-references in corlib etc. */
+#ifdef HAVE_SGEN_GC
+#define IS_GC_REFERENCE(t) FALSE
+#else
#define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
+#endif
/*
+ * mono_class_layout_fields:
+ * @class: a class
+ *
+ * Compute the placement of fields inside an object or struct, according to
+ * the layout rules and set the following fields in @class:
+ * - has_references (if the class contains instance references firled or structs that contain references)
+ * - has_static_refs (same, but for static fields)
+ * - instance_size (size of the object in memory)
+ * - class_size (size needed for the static fields)
+ * - size_inited (flag set when the instance_size is set)
+ *
* LOCKING: this is supposed to be called with the loader lock held.
*/
void
field = &class->fields [i];
- if (!field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+ 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;
break;
}
+ if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
+ /*
+ * For small structs, set min_align to at least the struct size, since the
+ * JIT memset/memcpy code assumes this and generates unaligned accesses
+ * otherwise. See #78990 for a testcase.
+ */
+ if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+ class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+ }
+
class->size_inited = 1;
/*
continue;
size = mono_type_size (field->type, &align);
- field->offset = class->class_size;
+ field->offset = class->sizes.class_size;
field->offset += align - 1;
field->offset &= ~(align - 1);
- class->class_size = field->offset + size;
+ class->sizes.class_size = field->offset + size;
}
}
/*
* mono_class_setup_methods:
+ * @class: a class
*
* Initializes the 'methods' array in the klass.
* Calling this method should be avoided if possible since it allocates a lot
* of long-living MonoMethod structures.
+ * Methods belonging to an interface are assigned a sequential slot starting
+ * from 0.
*/
void
mono_class_setup_methods (MonoClass *class)
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) {
+ 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);
{
guint startm, endm, i, j;
guint32 cols [MONO_PROPERTY_SIZE];
- MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
MonoProperty *properties;
guint32 last;
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);
+ mono_metadata_decode_row (&class->image->tables [MONO_TABLE_PROPERTY], i, cols, MONO_PROPERTY_SIZE);
properties [i - class->property.first].parent = class;
properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
mono_loader_unlock ();
}
+/*
+ * LOCKING: assumes the loader lock is held.
+ */
+static void
+inflate_event (MonoClass *class, MonoEvent *event, MonoInflatedGenericClass *gclass)
+{
+ event->parent = class;
+
+ if (event->add) {
+ MonoMethod *inflated = mono_class_inflate_generic_method_full (
+ event->add, class, gclass->generic_class.context);
+
+ event->add = mono_get_inflated_method (inflated);
+ }
+
+ if (event->remove) {
+ MonoMethod *inflated = mono_class_inflate_generic_method_full (
+ event->remove, class, gclass->generic_class.context);
+
+ event->remove = mono_get_inflated_method (inflated);
+ }
+
+ if (event->raise) {
+ MonoMethod *inflated = mono_class_inflate_generic_method_full (
+ event->raise, class, gclass->generic_class.context);
+
+ event->raise = mono_get_inflated_method (inflated);
+ }
+
+ if (event->other) {
+ MonoMethod **om = event->other;
+ int count = 0;
+ while (*om) {
+ count++;
+ om++;
+ }
+ om = event->other;
+ event->other = g_new0 (MonoMethod*, count + 1);
+ count = 0;
+ while (*om) {
+ MonoMethod *inflated = mono_class_inflate_generic_method_full (
+ *om, class, gclass->generic_class.context);
+
+ event->other [count++] = mono_get_inflated_method (inflated);
+ om++;
+ }
+ }
+}
+
static void
mono_class_setup_events (MonoClass *class)
{
guint startm, endm, i, j;
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;
mono_loader_unlock ();
return;
}
+
+ if (class->generic_class) {
+ MonoInflatedGenericClass *gclass;
+ MonoClass *gklass;
+
+ gclass = mono_get_inflated_generic_class (class->generic_class);
+ gklass = gclass->generic_class.container_class;
+
+ mono_class_setup_events (gklass);
+ class->event = gklass->event;
+
+ class->events = g_new0 (MonoEvent, class->event.count);
+
+ for (i = 0; i < class->event.count; i++) {
+ class->events [i] = gklass->events [i];
+ inflate_event (class, &class->events [i], gclass);
+ }
+
+ 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;
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);
+
+ mono_metadata_decode_row (&class->image->tables [MONO_TABLE_EVENT], i, cols, MONO_EVENT_SIZE);
event->parent = class;
event->attrs = cols [MONO_EVENT_FLAGS];
event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
int n = 0;
if (event->other == NULL) {
- event->other = g_new0 (MonoMethod*, 1);
+ event->other = g_new0 (MonoMethod*, 2);
} else {
while (event->other [n])
n++;
- event->other = g_realloc (event->other, (n + 1) * sizeof (MonoMethod*));
+ event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
}
event->other [n] = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+ /* NULL terminated */
+ event->other [n + 1] = NULL;
break;
}
default:
mono_loader_unlock ();
}
+/*
+ * Global pool of interface IDs, represented as a bitset.
+ * LOCKING: this is supposed to be accessed with the loader lock held.
+ */
+static MonoBitSet *global_interface_bitset = NULL;
+
+/*
+ * mono_unload_interface_ids:
+ * @bitset: bit set of interface IDs
+ *
+ * When an image is unloaded, the interface IDs associated with
+ * the image are put back in the global pool of IDs so the numbers
+ * can be reused.
+ */
+void
+mono_unload_interface_ids (MonoBitSet *bitset)
+{
+ mono_loader_lock ();
+ mono_bitset_sub (global_interface_bitset, bitset);
+ mono_loader_unlock ();
+}
+
+/*
+ * mono_get_unique_iid:
+ * @class: interface
+ *
+ * Assign a unique integer ID to the interface represented by @class.
+ * The ID will positive and as small as possible.
+ * LOCKING: this is supposed to be called with the loader lock held.
+ * Returns: the new ID.
+ */
static guint
mono_get_unique_iid (MonoClass *class)
{
- static GHashTable *iid_hash = NULL;
- static guint iid = 0;
-
- char *str;
- gpointer value;
+ int iid;
g_assert (MONO_CLASS_IS_INTERFACE (class));
- mono_loader_lock ();
-
- 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 (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
- mono_loader_unlock ();
- g_free (str);
- return GPOINTER_TO_INT (value);
+ if (!global_interface_bitset) {
+ global_interface_bitset = mono_bitset_new (128, 0);
+ }
+
+ iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
+ if (iid < 0) {
+ int old_size = mono_bitset_size (global_interface_bitset);
+ MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
+ mono_bitset_free (global_interface_bitset);
+ global_interface_bitset = new_set;
+ iid = old_size;
+ }
+ mono_bitset_set (global_interface_bitset, iid);
+ /* set the bit also in the per-image set */
+ if (class->image->interface_bitset) {
+ if (iid >= mono_bitset_size (class->image->interface_bitset)) {
+ MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
+ mono_bitset_free (class->image->interface_bitset);
+ class->image->interface_bitset = new_set;
+ }
} else {
- g_hash_table_insert (iid_hash, str, GINT_TO_POINTER (iid));
- ++iid;
+ class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
}
+ mono_bitset_set (class->image->interface_bitset, iid);
- mono_loader_unlock ();
+ if (mono_print_vtable) {
+ int generic_id;
+ char *type_name = mono_type_full_name (&class->byval_arg);
+ 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;
+ }
+ printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
+ g_free (type_name);
+ }
g_assert (iid <= 65535);
- return iid - 1;
+ return iid;
}
static void
return cached;
}
+/*
+ * LOCKING: this is supposed to be called with the loader lock held.
+ */
static int
setup_interface_offsets (MonoClass *class, int cur_slot)
{
}
class->max_interface_id = max_iid;
/* compute vtable offset for interfaces */
- class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
+ class->interface_offsets = g_malloc (sizeof (int) * (max_iid + 1));
for (i = 0; i <= max_iid; i++)
class->interface_offsets [i] = -1;
return cur_slot;
}
+/*
+ * Setup interface offsets for interfaces. Used by Ref.Emit.
+ */
+void
+mono_class_setup_interface_offsets (MonoClass *class)
+{
+ mono_loader_lock ();
+
+ setup_interface_offsets (class, 0);
+
+ mono_loader_unlock ();
+}
+
void
mono_class_setup_vtable (MonoClass *class)
{
MonoMethod **overrides;
MonoGenericContext *context;
+ guint32 type_token;
int onum = 0;
+ gboolean ok = TRUE;
if (class->vtable)
return;
return;
}
- if (class->generic_class)
+ mono_stats.generic_vtable_count ++;
+
+ if (class->generic_class) {
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 {
+ /* The following call fails if there are missing methods in the type */
+ ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+ }
- mono_class_get_overrides_full (class->image, class->type_token, &overrides, &onum, context);
- mono_class_setup_vtable_general (class, overrides, onum);
+ if (ok)
+ 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));
+ return;
}
/*
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);
- return;
- }
-
ifaces = mono_class_get_implemented_interfaces (class);
if (ifaces) {
for (i = 0; i < ifaces->len; i++) {
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;
*/
if (!(vtable [io + l])) {
MonoClass *parent = class->parent;
-
- if ((ic->interface_id <= parent->max_interface_id) &&
- (parent->interface_offsets [ic->interface_id]) &&
- parent->vtable)
- vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+
+ for (; parent; parent = parent->parent) {
+ if ((ic->interface_id <= parent->max_interface_id) &&
+ (parent->interface_offsets [ic->interface_id] != -1) &&
+ parent->vtable) {
+ vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+ }
+ }
}
if (!(vtable [io + l])) {
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(%s) in class %s.%s\n",
- ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
+ 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), FALSE);
+ msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
printf ("METHOD %s(%s)\n", cm->name, msig);
g_free (msig);
int j;
for (j = 0; j < k->method.count; ++j) {
MonoMethod *m1 = k->methods [j];
+ MonoMethodSignature *cmsig, *m1sig;
+
if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
continue;
+
+ cmsig = mono_method_signature (cm);
+ m1sig = mono_method_signature (m1);
+
+ if (!cmsig || !m1sig) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
+
if (!strcmp(cm->name, m1->name) &&
- mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
+ mono_metadata_signature_equal (cmsig, m1sig)) {
/* CAS - SecurityAction.InheritanceDemand */
if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
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);
- memcpy (class->vtable, vtable, sizeof (gpointer) * class->vtable_size);
+ /* Try to share the vtable with our parent. */
+ if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
+ class->vtable = class->parent->vtable;
+ } else {
+ class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
+ memcpy (class->vtable, vtable, sizeof (gpointer) * class->vtable_size);
+ }
if (mono_print_vtable) {
int icount = 0;
if (class->interface_offsets [i] != -1)
icount++;
- printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space,
- class->name, class->vtable_size, icount);
+ printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
+ class->vtable_size, icount);
for (i = 0; i < class->vtable_size; ++i) {
MonoMethod *cm;
cm = vtable [i];
if (cm) {
- printf (" slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
- cm->klass->name_space, cm->klass->name,
- cm->name);
+ printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
+ mono_method_full_name (cm, TRUE));
}
}
for (i = 0; i < class->interface_count; i++) {
ic = class->interfaces [i];
- printf (" slot %03d(%03d) %s.%s\n",
+ printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
class->interface_offsets [ic->interface_id],
- ic->method.count, ic->name_space, ic->name);
+ ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
}
for (k = class->parent; k ; k = k->parent) {
for (i = 0; i < k->interface_count; i++) {
ic = k->interfaces [i];
- printf (" slot %03d(%03d) %s.%s\n",
+ printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
class->interface_offsets [ic->interface_id],
- ic->method.count, ic->name_space, ic->name);
+ ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
}
}
}
}
}
+static MonoMethod *default_ghc = NULL;
+static MonoMethod *default_finalize = NULL;
+static int finalize_slot = -1;
+static int ghc_slot = -1;
+
+static void
+initialize_object_slots (MonoClass *class)
+{
+ int i;
+ if (default_ghc)
+ return;
+ if (class == mono_defaults.object_class) {
+ mono_class_setup_vtable (class);
+ for (i = 0; i < class->vtable_size; ++i) {
+ MonoMethod *cm = class->vtable [i];
+
+ if (!strcmp (cm->name, "GetHashCode"))
+ ghc_slot = i;
+ else if (!strcmp (cm->name, "Finalize"))
+ finalize_slot = i;
+ }
+
+ g_assert (ghc_slot > 0);
+ default_ghc = class->vtable [ghc_slot];
+
+ g_assert (finalize_slot > 0);
+ default_finalize = class->vtable [finalize_slot];
+ }
+}
+
+static GList*
+g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
+{
+ GList* n = mono_mempool_alloc (mp, sizeof (GList));
+ n->next = l;
+ n->prev = NULL;
+ n->data = datum;
+ return n;
+}
+
+static void
+setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
+{
+ MonoGenericContext *context;
+ int i;
+
+ context = g_new0 (MonoGenericContext, 1);
+ context->container = iface->generic_class->context->container;
+ context->gmethod = g_new0 (MonoGenericMethod, 1);
+ context->gmethod->generic_class = iface->generic_class;
+ context->gmethod->inst = iface->generic_class->inst;
+
+ for (i = 0; i < class->parent->method.count; i++) {
+ MonoMethod *m = class->parent->methods [i];
+ MonoMethod *inflated;
+ const char *mname, *iname;
+ gchar *name;
+
+ if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
+ iname = "System.Collections.Generic.ICollection`1.";
+ mname = m->name + 27;
+ } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
+ iname = "System.Collections.Generic.IEnumerable`1.";
+ mname = m->name + 27;
+ } else if (!strncmp (m->name, "InternalArray__", 15)) {
+ iname = "System.Collections.Generic.IList`1.";
+ mname = m->name + 15;
+ } else {
+ continue;
+ }
+
+ name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
+ strcpy (name, iname);
+ strcpy (name + strlen (iname), mname);
+
+ inflated = mono_class_inflate_generic_method (m, context);
+ class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
+ }
+}
+
/**
* mono_class_init:
* @class: the class to initialize
* compute the instance_size, class_size and other infos that cannot be
* computed at mono_class_get() time. Also compute a generic vtable and
* the method slot numbers. We use this infos later to create a domain
- * specific vtable.
+ * specific vtable.
+ *
+ * Returns TRUE on success or FALSE if there was a problem in loading
+ * the type (incorrect assemblies, missing assemblies, methods, etc).
*/
-void
+gboolean
mono_class_init (MonoClass *class)
{
int i;
- static MonoMethod *default_ghc = NULL;
- static MonoMethod *default_finalize = NULL;
- static int finalize_slot = -1;
- static int ghc_slot = -1;
MonoCachedClassInfo cached_info;
gboolean has_cached_info;
-
+ int class_init_ok = TRUE;
+
g_assert (class);
if (class->inited)
- return;
+ return TRUE;
/*g_print ("Init class %s\n", class->name);*/
if (class->inited) {
mono_loader_unlock ();
/* Somebody might have gotten in before us */
- return;
+ return TRUE;
}
if (class->init_pending) {
class->methods = g_new0 (MonoMethod *, class->method.count);
for (i = 0; i < class->method.count; i++) {
- MonoMethod *inflated = mono_class_inflate_generic_method (
- gklass->methods [i], gclass->generic_class.context);
+ MonoMethod *inflated = mono_class_inflate_generic_method_full (
+ gklass->methods [i], class, gclass->generic_class.context);
class->methods [i] = mono_get_inflated_method (inflated);
}
*prop = gklass->properties [i];
if (prop->get)
- prop->get = mono_class_inflate_generic_method (
- prop->get, gclass->generic_class.context);
+ prop->get = mono_class_inflate_generic_method_full (
+ prop->get, class, gclass->generic_class.context);
if (prop->set)
- prop->set = mono_class_inflate_generic_method (
- prop->set, gclass->generic_class.context);
+ prop->set = mono_class_inflate_generic_method_full (
+ prop->set, class, gclass->generic_class.context);
prop->parent = class;
}
guint32 cols [MONO_NESTED_CLASS_SIZE];
mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
- class->nested_classes = g_list_prepend (class->nested_classes, nclass);
+ class->nested_classes = g_list_prepend_mempool (class->nested_classes, class->image->mempool, nclass);
i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
}
*/
if (has_cached_info) {
class->instance_size = cached_info.instance_size;
- class->class_size = cached_info.class_size;
+ class->sizes.class_size = cached_info.class_size;
class->packing_size = cached_info.packing_size;
class->min_align = cached_info.min_align;
class->blittable = cached_info.blittable;
class->has_references = cached_info.has_references;
class->has_static_refs = cached_info.has_static_refs;
+ class->no_special_static_fields = cached_info.no_special_static_fields;
}
else
- if (!class->size_inited)
+ if (!class->size_inited){
mono_class_setup_fields (class);
+ if (class->exception_type || mono_loader_get_last_error ()){
+ class_init_ok = FALSE;
+ goto leave;
+ }
+ }
+
/* initialize method pointers */
if (class->rank) {
MonoMethod *ctor;
MonoMethodSignature *sig;
- class->method.count = class->rank > 1? 2: 1;
+ int count_generic = 0, first_generic = 0;
+
+ class->method.count = (class->rank > 1? 2: 1);
+
+ if (class->interface_count) {
+ for (i = 0; i < class->parent->method.count; i++) {
+ MonoMethod *m = class->parent->methods [i];
+ if (!strncmp (m->name, "InternalArray__", 15))
+ count_generic++;
+ }
+ first_generic = class->method.count;
+ class->method.count += class->interface_count * count_generic;
+ }
+
sig = mono_metadata_signature_alloc (class->image, class->rank);
sig->ret = &mono_defaults.void_class->byval_arg;
sig->pinvoke = TRUE;
for (i = 0; i < class->rank; ++i)
sig->params [i] = &mono_defaults.int32_class->byval_arg;
- ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
+ ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
ctor->klass = class;
ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
ctor->signature = sig;
ctor->name = ".ctor";
ctor->slot = -1;
- class->methods = g_new (MonoMethod*, class->method.count);
+ class->methods = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
class->methods [0] = ctor;
if (class->rank > 1) {
sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
for (i = 0; i < class->rank * 2; ++i)
sig->params [i] = &mono_defaults.int32_class->byval_arg;
- ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
+ ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
ctor->klass = class;
ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
ctor->slot = -1;
class->methods [1] = ctor;
}
- }
-
- mono_class_setup_supertypes (class);
-
- if (!default_ghc) {
- if (class == mono_defaults.object_class) {
- mono_class_setup_vtable (class);
- for (i = 0; i < class->vtable_size; ++i) {
- MonoMethod *cm = class->vtable [i];
-
- if (!strcmp (cm->name, "GetHashCode")) {
- ghc_slot = i;
- break;
- }
- }
-
- g_assert (ghc_slot > 0);
- default_ghc = class->vtable [ghc_slot];
- }
+ for (i = 0; i < class->interface_count; i++)
+ setup_generic_array_ifaces (class, class->interfaces [i], first_generic + i * count_generic);
}
- if (!default_finalize) {
- if (class == mono_defaults.object_class) {
- mono_class_setup_vtable (class);
- for (i = 0; i < class->vtable_size; ++i) {
- MonoMethod *cm = class->vtable [i];
-
- if (!strcmp (cm->name, "Finalize")) {
- finalize_slot = i;
- break;
- }
- }
-
- g_assert (finalize_slot > 0);
+ mono_class_setup_supertypes (class);
- default_finalize = class->vtable [finalize_slot];
- }
- }
+ if (!default_ghc)
+ initialize_object_slots (class);
/*
* If possible, avoid the creation of the generic vtable by requesting
}
else {
mono_class_setup_vtable (class);
-
+
+ if (class->exception_type || mono_loader_get_last_error ()){
+ class_init_ok = FALSE;
+ goto leave;
+ }
+
class->ghcimpl = 1;
if (class->parent) {
MonoMethod *cmethod = class->vtable [ghc_slot];
}
}
- class->inited = 1;
- class->init_pending = 0;
-
- mono_loader_unlock ();
-
if (MONO_CLASS_IS_INTERFACE (class)) {
/*
* class->interface_offsets is needed for the castclass/isinst code, so
setup_interface_offsets (class, 0);
}
+ leave:
+ class->inited = 1;
+ class->init_pending = 0;
+
+ mono_loader_unlock ();
+
if (mono_debugger_class_init_func)
mono_debugger_class_init_func (class);
+
+ return class_init_ok;
}
/*
const char *name = class->name;
const char *nspace = class->name_space;
- if (MONO_CLASS_IS_INTERFACE (class))
- class->interface_id = mono_get_unique_iid (class);
-
class->this_arg.byref = 1;
class->this_arg.data.klass = class;
class->this_arg.type = MONO_TYPE_CLASS;
}
class->this_arg.type = class->byval_arg.type = t;
}
+
+ if (MONO_CLASS_IS_INTERFACE (class))
+ class->interface_id = mono_get_unique_iid (class);
+
}
/*
}
if (!MONO_CLASS_IS_INTERFACE (class)) {
+ /* Imported COM Objects always derive from __ComObject. */
+ if (MONO_CLASS_IS_IMPORT (class)) {
+ if (parent == mono_defaults.object_class)
+ parent = mono_defaults.com_object_class;
+ }
class->parent = parent;
+
if (!parent)
g_assert_not_reached (); /* FIXME */
class->marshalbyref = parent->marshalbyref;
class->contextbound = parent->contextbound;
class->delegate = parent->delegate;
+ if (MONO_CLASS_IS_IMPORT (class))
+ class->is_com_object = 1;
+ else
+ class->is_com_object = parent->is_com_object;
if (system_namespace) {
if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
}
/*
+ * mono_class_setup_supertypes:
+ * @class: a class
+ *
+ * Build the data structure needed to make fast type checks work.
+ * This currently sets two fields in @class:
+ * - idepth: distance between @class and System.Object in the type
+ * hierarchy + 1
+ * - supertypes: array of classes: each element has a class in the hierarchy
+ * starting from @class up to System.Object
+ *
* LOCKING: this assumes the loader lock is held
*/
void
class->idepth = 1;
ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
- class->supertypes = g_new0 (MonoClass *, ms);
+ class->supertypes = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClass *) * ms);
if (class->parent) {
class->supertypes [class->idepth - 1] = class;
}
}
-/*
- * 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)
+MonoGenericInst *
+mono_get_shared_generic_inst (MonoGenericContainer *container)
{
MonoGenericInst *nginst;
int i;
gclass->context = &container->context;
gclass->container_class = container->klass;
- gclass->inst = get_shared_inst (container);
+ gclass->inst = mono_get_shared_generic_inst (container);
if (!is_dynamic) {
MonoGenericClass *cached = mono_metadata_lookup_generic_class (gclass);
}
/**
- * @image: context where the image is created
+ * mono_class_create_from_typedef:
+ * @image: image where the token is valid
* @type_token: typedef token
+ *
+ * Create the MonoClass* representing the specified type token.
+ * @type_token must be a TypeDef token.
*/
static MonoClass *
mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
guint icount = 0;
MonoClass **interfaces;
guint32 field_last, method_last;
+ guint32 nesting_tokeen;
mono_loader_lock ();
name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
- class = g_malloc0 (sizeof (MonoClass));
+ class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
class->name = name;
class->name_space = nspace;
if (cols [MONO_TYPEDEF_EXTENDS]) {
parent = mono_class_get_full (
image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+ if (parent == NULL){
+ g_hash_table_remove (image->class_cache, GUINT_TO_POINTER (type_token));
+ mono_loader_unlock ();
+ return NULL;
+ }
}
+ /* do this early so it's available for interfaces in setup_mono_type () */
+ if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token)))
+ class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
+
mono_class_setup_parent (class, parent);
+ /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
mono_class_setup_mono_type (class);
if (!class->enumtype) {
- mono_metadata_interfaces_from_typedef_full (image, type_token, &interfaces, &icount, context);
+ if (!mono_metadata_interfaces_from_typedef_full (
+ image, type_token, &interfaces, &icount, context)){
+ mono_loader_unlock ();
+ return NULL;
+ }
class->interfaces = interfaces;
class->interface_count = icount;
if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
class->unicode = 1;
- /* fixme: maybe we must set this on windows
+
+#if PLATFORM_WIN32
if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
class->unicode = 1;
- */
+#endif
class->cast_class = class->element_class = class;
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 we inherit any type parameters from our containing class, we need to modify
- * their `owner'.
- */
- 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.
MonoClass *klass, *gklass;
int i;
- if (gclass->is_initialized)
+ mono_loader_lock ();
+ if (gclass->is_initialized) {
+ mono_loader_unlock ();
return;
- gclass->is_initialized = TRUE;
+ }
if (!gclass->klass)
gclass->klass = g_malloc0 (sizeof (MonoClass));
gklass = gclass->generic_class.container_class;
- klass->nested_in = gklass->nested_in;
+ if (gklass->nested_in) {
+ /*
+ * FIXME: the nested type context should include everything the
+ * nesting context should have, but it may also have additional
+ * generic parameters...
+ */
+ MonoType *inflated = mono_class_inflate_generic_type (
+ &gklass->nested_in->byval_arg, gclass->generic_class.context);
+ klass->nested_in = mono_class_from_mono_type (inflated);
+ }
klass->name = gklass->name;
klass->name_space = gklass->name_space;
klass->image = gklass->image;
klass->flags = gklass->flags;
+ klass->type_token = gklass->type_token;
klass->generic_class = &gclass->generic_class;
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;
+ klass->sizes.class_size = gklass->sizes.class_size;
klass->size_inited = 1;
klass->inited = 1;
i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, i + 1);
}
- if (gclass->generic_class.is_dynamic) {
- MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) gclass;
-
- if (dgclass->parent)
- klass->parent = mono_class_from_mono_type (dgclass->parent);
- } else if (gklass->parent) {
+ if (gklass->parent) {
MonoType *inflated = mono_class_inflate_generic_type (
&gklass->parent->byval_arg, gclass->generic_class.context);
if (klass->parent)
mono_class_setup_parent (klass, klass->parent);
+
+ if (MONO_CLASS_IS_INTERFACE (klass))
+ setup_interface_offsets (klass, 0);
+ gclass->is_initialized = TRUE;
+ mono_loader_unlock ();
}
MonoClass *
klass = param->pklass = g_new0 (MonoClass, 1);
for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
- ;
-
- pos = 0;
- if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
- klass->parent = param->constraints [0];
- pos++;
- } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
- klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
- else
- klass->parent = mono_defaults.object_class;
-
- if (count - pos > 0) {
- klass->interface_count = count - pos;
- klass->interfaces = g_new0 (MonoClass *, count - pos);
- for (i = pos; i < count; i++)
- klass->interfaces [i - pos] = param->constraints [i];
- }
-
- g_assert (param->name && param->owner);
-
- klass->name = param->name;
- klass->name_space = "";
- klass->image = image;
- klass->inited = TRUE;
- klass->cast_class = klass->element_class = klass;
- klass->enum_basetype = &klass->element_class->byval_arg;
- klass->flags = TYPE_ATTRIBUTE_PUBLIC;
-
- klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
- klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
- klass->this_arg.byref = TRUE;
-
- klass->generic_container = param->owner;
-
- mono_class_setup_supertypes (klass);
-
- return klass;
-}
-
-static MonoClass *
-my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
-{
- MonoClass *klass;
+ ;
- if (param->pklass)
- return param->pklass;
+ pos = 0;
+ if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
+ klass->parent = param->constraints [0];
+ pos++;
+ } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
+ klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
+ else
+ klass->parent = mono_defaults.object_class;
- klass = g_new0 (MonoClass, 1);
+ if (count - pos > 0) {
+ klass->interface_count = count - pos;
+ klass->interfaces = g_new0 (MonoClass *, count - pos);
+ for (i = pos; i < count; i++)
+ klass->interfaces [i - pos] = param->constraints [i];
+ }
if (param->name)
klass->name = param->name;
else
klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+
klass->name_space = "";
- klass->image = mono_defaults.corlib;
+
+ if (image)
+ klass->image = image;
+ else if (is_mvar && param->method && param->method->klass)
+ klass->image = param->method->klass->image;
+ else if (param->owner && param->owner->klass)
+ klass->image = param->owner->klass->image;
+ else
+ klass->image = mono_defaults.corlib;
+
klass->inited = TRUE;
klass->cast_class = klass->element_class = klass;
klass->enum_basetype = &klass->element_class->byval_arg;
klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
klass->this_arg.byref = TRUE;
- klass->generic_container = param->owner;
-
mono_class_setup_supertypes (klass);
return klass;
{
MonoClass *result;
MonoClass *el_class;
- static GHashTable *ptr_hash = NULL;
+ MonoImage *image;
+ char *name;
+
+ el_class = mono_class_from_mono_type (type);
+ image = el_class->image;
mono_loader_lock ();
- if (!ptr_hash)
- ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
- el_class = mono_class_from_mono_type (type);
- if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
+ if (!image->ptr_cache)
+ image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+
+ if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
mono_loader_unlock ();
return result;
}
- result = g_new0 (MonoClass, 1);
+ result = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
result->parent = NULL; /* no parent for PTR types */
result->name_space = el_class->name_space;
- result->name = g_strdup_printf ("%s*", el_class->name);
+ name = g_strdup_printf ("%s*", el_class->name);
+ result->name = mono_mempool_strdup (image->mempool, name);
+ g_free (name);
result->image = el_class->image;
result->inited = TRUE;
result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
mono_class_setup_supertypes (result);
- g_hash_table_insert (ptr_hash, el_class, result);
+ g_hash_table_insert (image->ptr_cache, el_class, result);
mono_loader_unlock ();
MonoClass *result;
static GHashTable *ptr_hash = NULL;
+ /* FIXME: These should be allocate from a mempool as well, but which one ? */
+
mono_loader_lock ();
if (!ptr_hash)
result = g_new0 (MonoClass, 1);
result->parent = NULL; /* no parent for PTR types */
- result->name = "System";
- result->name_space = "MonoFNPtrFakeClass";
- result->image = NULL; /* need to fix... */
+ result->name_space = "System";
+ result->name = "MonoFNPtrFakeClass";
+ result->image = mono_defaults.corlib; /* need to fix... */
result->inited = TRUE;
result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
/* Can pointers get boxed? */
return gclass->klass;
}
case MONO_TYPE_VAR:
- return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
+ return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
case MONO_TYPE_MVAR:
- return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
+ return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
default:
g_warning ("implement me 0x%02x\n", type->type);
g_assert_not_reached ();
/**
* @image: context where the image is created
* @type_spec: typespec token
+ * @context: the generic context used to evaluate generic instantiations in
*/
static MonoClass *
-mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
- MonoGenericContext *context)
+mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
{
- MonoType *type, *inflated;
- MonoClass *class;
-
- type = mono_type_create_from_typespec_full (image, context, type_spec);
-
- switch (type->type) {
- case MONO_TYPE_ARRAY:
- class = mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
- break;
- case MONO_TYPE_SZARRAY:
- class = mono_array_class_get (type->data.klass, 1);
- break;
- case MONO_TYPE_PTR:
- class = mono_ptr_class_get (type->data.type);
- break;
- case MONO_TYPE_GENERICINST: {
- MonoInflatedGenericClass *gclass;
- gclass = mono_get_inflated_generic_class (type->data.generic_class);
- g_assert (gclass->klass);
- class = gclass->klass;
- break;
- }
- default:
- /* it seems any type can be stored in TypeSpec as well */
- class = mono_class_from_mono_type (type);
- break;
+ MonoType *t = mono_type_create_from_typespec (image, type_spec);
+ if (!t)
+ return NULL;
+ if (context && (context->gclass || context->gmethod)) {
+ MonoType *inflated = inflate_generic_type (t, context);
+ if (inflated)
+ t = inflated;
}
-
- if (!class || !context || (!context->gclass && !context->gmethod))
- return class;
-
- inflated = mono_class_inflate_generic_type (&class->byval_arg, context);
-
- return mono_class_from_mono_type (inflated);
+ return mono_class_from_mono_type (t);
}
/**
mono_loader_lock ();
+ if (!image->array_cache)
+ image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+
if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
for (; list; list = list->next) {
class = list->data;
- if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
+ if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
mono_loader_unlock ();
return class;
}
if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
parent = mono_class_from_name (image, "System", "Array");
corlib_type = TRUE;
- } else if (mono_defaults.generic_array_class) {
- MonoType *inflated, **args;
-
- args = g_new0 (MonoType *, 1);
- args [0] = &eclass->byval_arg;
-
- inflated = mono_class_bind_generic_parameters (
- &mono_defaults.generic_array_class->byval_arg, 1, args);
- parent = mono_class_from_mono_type (inflated);
-
- if (!parent->inited)
- mono_class_init (parent);
} else {
parent = mono_defaults.array_class;
if (!parent->inited)
mono_class_init (parent);
}
- class = g_malloc0 (sizeof (MonoClass));
+ class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
class->image = image;
class->name_space = eclass->name_space;
memset (name + nsize + 1, ',', rank - 1);
name [nsize + rank] = ']';
name [nsize + rank + 1] = 0;
- class->name = name;
+ class->name = mono_mempool_strdup (image->mempool, name);
+ g_free (name);
class->type_token = 0;
/* all arrays are marked serializable and sealed, bug #42779 */
class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
(eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
class->parent = parent;
class->instance_size = mono_class_instance_size (class->parent);
- class->class_size = 0;
+ class->sizes.element_size = mono_class_array_element_size (eclass);
mono_class_setup_supertypes (class);
+
+ if (mono_defaults.generic_ilist_class) {
+ MonoClass *fclass = NULL;
+ int i;
+
+ if (eclass->valuetype) {
+ if (eclass == mono_defaults.int16_class)
+ fclass = mono_defaults.uint16_class;
+ if (eclass == mono_defaults.uint16_class)
+ fclass = mono_defaults.int16_class;
+ if (eclass == mono_defaults.int32_class)
+ fclass = mono_defaults.uint32_class;
+ if (eclass == mono_defaults.uint32_class)
+ fclass = mono_defaults.int32_class;
+ if (eclass == mono_defaults.int64_class)
+ fclass = mono_defaults.uint64_class;
+ if (eclass == mono_defaults.uint64_class)
+ fclass = mono_defaults.int64_class;
+ if (eclass == mono_defaults.byte_class)
+ fclass = mono_defaults.sbyte_class;
+ if (eclass == mono_defaults.sbyte_class)
+ fclass = mono_defaults.byte_class;
+
+ class->interface_count = fclass ? 2 : 1;
+ } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
+ class->interface_count = 2 + eclass->interface_count;
+ } else {
+ class->interface_count = eclass->idepth + eclass->interface_count;
+ }
+
+ class->interfaces = g_new0 (MonoClass *, class->interface_count);
+
+ for (i = 0; i < class->interface_count; i++) {
+ MonoType *inflated, **args;
+ MonoClass *iface;
+
+ if (eclass->valuetype)
+ iface = (i == 0) ? eclass : fclass;
+ else if (MONO_CLASS_IS_INTERFACE (eclass)) {
+ if (i == 0)
+ iface = mono_defaults.object_class;
+ else if (i == 1)
+ iface = eclass;
+ else
+ iface = eclass->interfaces [i - 2];
+ } else {
+ if (i < eclass->idepth)
+ iface = eclass->supertypes [i];
+ else
+ iface = eclass->interfaces [i - eclass->idepth];
+ }
+
+ args = g_new0 (MonoType *, 1);
+ args [0] = &iface->byval_arg;
+
+ inflated = mono_class_bind_generic_parameters (
+ &mono_defaults.generic_ilist_class->byval_arg, 1, args);
+
+ class->interfaces [i] = mono_class_from_mono_type (inflated);
+ }
+ }
+
if (eclass->generic_class)
mono_class_init (eclass);
if (!eclass->size_inited)
class->element_class = eclass;
if ((rank > 1) || bounded) {
- MonoArrayType *at = g_new0 (MonoArrayType, 1);
+ MonoArrayType *at = mono_mempool_alloc0 (image->mempool, sizeof (MonoArrayType));
class->byval_arg.type = MONO_TYPE_ARRAY;
class->byval_arg.data.array = at;
at->eklass = eclass;
if (!klass->inited)
mono_class_init (klass);
- return klass->class_size;
+ /* in arrays, sizes.class_size is unioned with element_size
+ * and arrays have no static fields
+ */
+ if (klass->rank)
+ return 0;
+ return klass->sizes.class_size;
}
/*
return 0;
}
-void *
-mono_vtable_get_static_field_data (MonoVTable *vt)
-{
- return vt->data;
-}
-
MonoProperty*
mono_class_get_property_from_name (MonoClass *klass, const char *name)
{
}
/**
- * mono_class_get:
+ * mono_class_get_full:
* @image: the image where the class resides
* @type_token: the token for the class
- * @at: an optional pointer to return the array element type
+ * @context: the generic context used to evaluate generic instantiations in
*
* Returns: the MonoClass that represents @type_token in @image
*/
-static MonoClass *
-_mono_class_get (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+MonoClass *
+mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
{
MonoClass *class = NULL;
MonoClass *
mono_class_get (MonoImage *image, guint32 type_token)
{
- return _mono_class_get (image, type_token, NULL);
+ return mono_class_get_full (image, type_token, NULL);
}
-MonoClass *
-mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
+/**
+ * mono_image_init_name_cache:
+ *
+ * Initializes the class name cache stored in image->name_cache.
+ *
+ * LOCKING: Acquires the loader lock.
+ */
+void
+mono_image_init_name_cache (MonoImage *image)
{
- MonoClass *class = _mono_class_get (image, type_token, context);
- MonoType *inflated;
+ MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
+ guint32 cols [MONO_TYPEDEF_SIZE];
+ const char *name;
+ const char *nspace;
+ guint32 i, visib, nspace_index;
+ GHashTable *name_cache2, *nspace_table;
- if (!class || !context || (!context->gclass && !context->gmethod))
- return class;
+ mono_loader_lock ();
- switch (class->byval_arg.type) {
- case MONO_TYPE_GENERICINST:
- if (!class->generic_class->inst->is_open)
- return class;
- break;
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- break;
- default:
- return class;
+ image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (image->dynamic) {
+ mono_loader_unlock ();
+ return;
}
- inflated = inflate_generic_type (&class->byval_arg, context);
- if (!inflated)
- return class;
+ /* Temporary hash table to avoid lookups in the nspace_table */
+ name_cache2 = g_hash_table_new (NULL, NULL);
+
+ for (i = 1; i <= t->rows; ++i) {
+ mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
+ /* nested types are accessed from the nesting name */
+ visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+ continue;
+ name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+ nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+
+ nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
+ nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
+ if (!nspace_table) {
+ nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+ g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
+ nspace_table);
+ }
+ g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
+ }
+
+ /* Load type names from EXPORTEDTYPES table */
+ {
+ MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
+ guint32 cols [MONO_EXP_TYPE_SIZE];
+ int i;
+
+ for (i = 0; i < t->rows; ++i) {
+ mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
+ name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
+ nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
+
+ nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
+ nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
+ if (!nspace_table) {
+ nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+ g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
+ nspace_table);
+ }
+ g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
+ }
+ }
+
+ g_hash_table_destroy (name_cache2);
+
+ mono_loader_unlock ();
+}
+
+void
+mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
+ const char *name, guint32 index)
+{
+ GHashTable *nspace_table;
+ GHashTable *name_cache;
+
+ mono_loader_lock ();
- return mono_class_from_mono_type (inflated);
+ if (!image->name_cache)
+ mono_image_init_name_cache (image);
+
+ name_cache = image->name_cache;
+ if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
+ nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
+ }
+ g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
+
+ mono_loader_unlock ();
}
typedef struct {
* Obtains a MonoClass with a given namespace and a given name which
* is located in the given MonoImage. The namespace and name
* lookups are case insensitive.
- *
- * You can also pass @NULL to the image, and that will lookup for
- * a type with the given namespace and name in all of the loaded
- * assemblies: notice that since there might be a name clash in this
- * case, passing @NULL is not encouraged if you need a precise type.
- *
*/
MonoClass *
mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
mono_loader_lock ();
+ if (!image->name_cache)
+ mono_image_init_name_cache (image);
+
user_data.key = name_space;
user_data.value = NULL;
g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
*
* Obtains a MonoClass with a given namespace and a given name which
* is located in the given MonoImage.
- *
- * You can also pass `NULL' to the image, and that will lookup for
- * a type with the given namespace and name in all of the loaded
- * assemblies: notice that since there might be a name clash in this
- * case, passing NULL is not encouraged if you need a precise type.
- *
*/
MonoClass *
mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
name = buf;
}
+ if (get_class_from_name) {
+ gboolean res = get_class_from_name (image, name_space, name, &class);
+ if (res) {
+ if (nested)
+ return class ? return_nested_in (class, nested) : NULL;
+ else
+ return class;
+ }
+ }
+
mono_loader_lock ();
+ if (!image->name_cache)
+ mono_image_init_name_cache (image);
+
nspace_table = g_hash_table_lookup (image->name_cache, name_space);
if (nspace_table)
if (nested)
return return_nested_in (class, nested);
return class;
+ } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
+ MonoAssembly **references = image->references;
+ if (!references [idx - 1])
+ mono_assembly_load_reference (image, idx - 1);
+ g_assert (references == image->references);
+ g_assert (references [idx - 1]);
+ if (references [idx - 1] == (gpointer)-1)
+ return NULL;
+ else
+ /* FIXME: Cycle detection */
+ return mono_class_from_name (references [idx - 1]->image, name_space, name);
} else {
g_error ("not yet implemented");
}
mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
gboolean check_interfaces)
{
- again:
g_assert (klassc->idepth > 0);
if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
if ((klassc->interface_id <= klass->max_interface_id) &&
if (klassc == mono_defaults.object_class)
return TRUE;
- if (klass->generic_class && klass->generic_class->is_dynamic) {
- MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) klass->generic_class;
-
- if (!dgclass->parent)
- return FALSE;
-
- if (mono_metadata_type_equal (dgclass->parent, &klassc->byval_arg))
- return TRUE;
- klass = mono_class_from_mono_type (dgclass->parent);
- goto again;
- }
-
return FALSE;
}
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->interface_id <= oklass->max_interface_id) &&
(oklass->interface_offsets [klass->interface_id] != -1))
return TRUE;
- } else
- if (klass->rank) {
- MonoClass *eclass, *eoclass;
-
- if (oklass->rank != klass->rank)
- return FALSE;
-
- /* vectors vs. one dimensional arrays */
- if (oklass->byval_arg.type != klass->byval_arg.type)
- return FALSE;
+ } else if (klass->rank) {
+ MonoClass *eclass, *eoclass;
- eclass = klass->cast_class;
- eoclass = oklass->cast_class;
+ if (oklass->rank != klass->rank)
+ return FALSE;
+ /* vectors vs. one dimensional arrays */
+ if (oklass->byval_arg.type != klass->byval_arg.type)
+ return FALSE;
- /*
- * a is b does not imply a[] is b[] when a is a valuetype, and
- * b is a reference type.
- */
+ eclass = klass->cast_class;
+ eoclass = oklass->cast_class;
- if (eoclass->valuetype) {
- if ((eclass == mono_defaults.enum_class) ||
- (eclass == mono_defaults.enum_class->parent) ||
- (eclass == mono_defaults.object_class))
- return FALSE;
- }
+ /*
+ * a is b does not imply a[] is b[] when a is a valuetype, and
+ * b is a reference type.
+ */
- return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
+ if (eoclass->valuetype) {
+ if ((eclass == mono_defaults.enum_class) ||
+ (eclass == mono_defaults.enum_class->parent) ||
+ (eclass == mono_defaults.object_class))
+ return FALSE;
}
- else
- 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 mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
+ } else if (mono_class_is_nullable (klass))
+ return (mono_class_is_assignable_from (klass->cast_class, oklass));
+ else if (klass == mono_defaults.object_class)
+ return TRUE;
- return FALSE;
+ return mono_class_has_parent (oklass, klass);
}
/*
mono_class_get_finalizer (MonoClass *klass)
{
MonoCachedClassInfo cached_info;
- static int finalize_slot = -1;
-
- if (finalize_slot < 0) {
- int i;
- MonoClass* obj_class = mono_get_object_class ();
- mono_class_setup_vtable (obj_class);
- for (i = 0; i < obj_class->vtable_size; ++i) {
- MonoMethod *cm = obj_class->vtable [i];
-
- if (!strcmp (mono_method_get_name (cm), "Finalize")) {
- finalize_slot = i;
- break;
- }
- }
- }
+ if (!klass->inited)
+ mono_class_init (klass);
if (!klass->has_finalize)
return NULL;
gint32
mono_array_element_size (MonoClass *ac)
{
- return mono_class_array_element_size (ac->element_class);
+ g_assert (ac->rank);
+ return ac->sizes.element_size;
}
gpointer
switch (token & 0xff000000) {
case MONO_TOKEN_TYPE_DEF:
- case MONO_TOKEN_TYPE_REF: {
+ case MONO_TOKEN_TYPE_REF:
+ case MONO_TOKEN_TYPE_SPEC: {
MonoClass *class;
if (handle_class)
*handle_class = mono_defaults.typehandle_class;
/* We return a MonoType* as handle */
return &class->byval_arg;
}
- case MONO_TOKEN_TYPE_SPEC: {
- MonoClass *class;
- 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));
return get_cached_class_info (klass, res);
}
+void
+mono_install_get_class_from_name (MonoGetClassFromName func)
+{
+ get_class_from_name = func;
+}
+
MonoImage*
mono_class_get_image (MonoClass *klass)
{
return &klass->byval_arg;
}
+/**
+ * mono_class_get_type_token
+ * @klass: the MonoClass to act on
+ *
+ * This method returns type token for the class.
+ *
+ * Returns: the type token for the class.
+ */
+guint32
+mono_class_get_type_token (MonoClass *klass)
+{
+ return klass->type_token;
+}
+
/**
* mono_class_get_byref_type:
* @klass: the MonoClass to act on
return field->type->attrs;
}
+/**
+ * mono_field_get_data;
+ * @field: the MonoClassField to act on
+ *
+ * Returns: pointer to the metadata constant value or to the field
+ * data if it has an RVA flag.
+ */
+const char *
+mono_field_get_data (MonoClassField *field)
+{
+ return field->data;
+}
+
/**
* mono_property_get_name:
* @prop: the MonoProperty to act on
return TRUE;
}
+/**
+ * mono_classes_init:
+ *
+ * Initialize the resources used by this module.
+ */
+void
+mono_classes_init (void)
+{
+}
+
+/**
+ * mono_classes_cleanup:
+ *
+ * Free the resources used by this module.
+ */
+void
+mono_classes_cleanup (void)
+{
+ IOffsetInfo *cached_info, *next;
+
+ if (global_interface_bitset)
+ mono_bitset_free (global_interface_bitset);
+
+ for (cached_info = cached_offset_info; cached_info;) {
+ next = cached_info->next;
+
+ g_free (cached_info);
+ cached_info = next;
+ }
+}
+
/**
* mono_class_get_exception_for_failure:
* @klass: class in which the failure was detected
mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
return (MonoException*) exc;
}
- /* TODO - handle other class related failures */
- default:
+ case MONO_EXCEPTION_TYPE_LOAD:
+ return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
+
+ default: {
+ MonoLoaderError *error;
+ MonoException *ex;
+
+ error = mono_loader_get_last_error ();
+ if (error != NULL){
+ ex = mono_loader_error_prepare_exception (error);
+ return ex;
+ }
+
+ /* TODO - handle other class related failures */
return NULL;
}
+ }
}