#include <stdlib.h>
#include <signal.h>
#include <mono/metadata/image.h>
+#include <mono/metadata/assembly.h>
#include <mono/metadata/cil-coff.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/reflection.h>
#include <mono/os/gc_wrapper.h>
-/*
- * Uncomment this to enable GC aware auto layout: in this mode, reference
- * fields are grouped together inside objects, increasing collector
- * performance.
- * Requires that all classes whose layout is known to the runtime be annotated
- * with [StructLayout (LayoutKind.Sequential)]
- */
-//#define GC_AWARE_AUTO_LAYOUT
-
#define CSIZE(x) (sizeof (x) / 4)
MonoStats mono_stats;
const char *name, *nspace;
MonoClass *res;
MonoAssembly **references;
- MonoImageOpenStatus status;
mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
break;
}
- mono_image_load_references (image, &status);
references = image->references;
if (!references || !references [idx-1]) {
/*
return mono_class_from_name (image, nspace, name);
}
-MonoMarshalType *
-mono_marshal_load_type_info (MonoClass* klass)
+static MonoType*
+dup_type (MonoType* t)
{
- int i, j, count = 0, native_size = 0;
- MonoMarshalType *info;
- guint32 layout;
-
- g_assert (klass != NULL);
-
- if (klass->marshal_info)
- return klass->marshal_info;
+ MonoType *r = g_new0 (MonoType, 1);
+ *r = *t;
+ return r;
+}
- if (!klass->inited)
- mono_class_init (klass);
+static void
+mono_type_get_name_recurse (MonoType *type, GString *str)
+{
+ MonoClass *klass;
- for (i = 0; i < klass->field.count; ++i) {
- if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
- count++;
+ switch (type->type) {
+ case MONO_TYPE_ARRAY: {
+ int i, rank = type->data.array->rank;
+
+ mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str);
+ g_string_append_c (str, '[');
+ for (i = 1; i < rank; i++)
+ g_string_append_c (str, ',');
+ g_string_append_c (str, ']');
+ break;
}
+ case MONO_TYPE_SZARRAY:
+ mono_type_get_name_recurse (&type->data.klass->byval_arg, str);
+ g_string_append (str, "[]");
+ break;
+ case MONO_TYPE_PTR:
+ mono_type_get_name_recurse (type->data.type, str);
+ g_string_append_c (str, '*');
+ break;
+ default:
+ klass = mono_class_from_mono_type (type);
+ if (klass->nested_in) {
+ mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
+ g_string_append_c (str, '+');
+ }
+ if (*klass->name_space) {
+ g_string_append (str, klass->name_space);
+ g_string_append_c (str, '.');
+ }
+ g_string_append (str, klass->name);
+ break;
+ }
+}
- layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
-
- klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
- info->num_fields = count;
-
- /* Try to find a size for this type in metadata */
- mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
-
- if (klass->parent) {
- int parent_size = mono_class_native_size (klass->parent, NULL);
+/*
+ * mono_type_get_name:
+ * @type: a type
+ *
+ * Returns the string representation for type as required by System.Reflection.
+ * The inverse of mono_reflection_parse_type ().
+ */
+char*
+mono_type_get_name (MonoType *type)
+{
+ GString* result = g_string_new ("");
+ mono_type_get_name_recurse (type, result);
- /* Add parent size to real size */
- native_size += parent_size;
- info->native_size = parent_size;
- }
-
- for (j = i = 0; i < klass->field.count; ++i) {
- int size, align;
-
- if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
+ if (type->byref)
+ g_string_append_c (result, '&');
- if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
- mono_metadata_field_info (klass->image, klass->field.first + i,
- NULL, NULL, &info->fields [j].mspec);
+ return g_string_free (result, FALSE);
+}
- info->fields [j].field = &klass->fields [i];
+gboolean
+mono_class_is_open_constructed_type (MonoType *t)
+{
+ switch (t->type) {
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ return TRUE;
+ case MONO_TYPE_SZARRAY:
+ return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
+ case MONO_TYPE_ARRAY:
+ return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
+ case MONO_TYPE_PTR:
+ return mono_class_is_open_constructed_type (t->data.type);
+ case MONO_TYPE_GENERICINST: {
+ MonoGenericInst *ginst = t->data.generic_inst;
+ int i;
- switch (layout) {
- case TYPE_ATTRIBUTE_AUTO_LAYOUT:
- case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
- size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
- &align, TRUE, klass->unicode);
- align = klass->packing_size ? MIN (klass->packing_size, align): align;
- info->fields [j].offset = info->native_size;
- info->fields [j].offset += align - 1;
- info->fields [j].offset &= ~(align - 1);
- info->native_size = info->fields [j].offset + size;
- break;
- case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
- /* FIXME: */
- info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
- info->native_size = klass->instance_size - sizeof (MonoObject);
- break;
- }
- j++;
+ if (mono_class_is_open_constructed_type (ginst->generic_type))
+ return TRUE;
+ for (i = 0; i < ginst->type_argc; i++)
+ if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
+ return TRUE;
+ return FALSE;
}
+ default:
+ return FALSE;
+ }
+}
- if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
- info->native_size = MAX (native_size, info->native_size);
+MonoType*
+mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst)
+{
+ switch (type->type) {
+ case MONO_TYPE_MVAR:
+ if (ginst)
+ return dup_type (ginst->type_argv [type->data.generic_param->num]);
+ else
+ return type;
+ case MONO_TYPE_VAR: {
+ MonoType *t = ginst->type_argv [type->data.generic_param->num];
+
+ if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR))
+ return type;
+ else
+ return dup_type (t);
+ }
+ case MONO_TYPE_SZARRAY: {
+ MonoClass *eclass = type->data.klass;
+ MonoClass *nclass;
+ MonoType *nt;
+ if (eclass->byval_arg.type == MONO_TYPE_MVAR) {
+ nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
+ } else if (eclass->byval_arg.type == MONO_TYPE_VAR) {
+ nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
+ } else {
+ return type;
+ }
+ nt = dup_type (type);
+ nt->data.klass = nclass;
+ return nt;
+ }
+ default:
+ return type;
}
+ return type;
+}
+
+MonoMethodSignature*
+mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *ginst)
+{
+ MonoMethodSignature *res;
+ int i;
+ res = mono_metadata_signature_alloc (image, sig->param_count);
+ res->ret = mono_class_inflate_generic_type (sig->ret, ginst);
+ for (i = 0; i < sig->param_count; ++i) {
+ res->params [i] = mono_class_inflate_generic_type (sig->params [i], ginst);
+ }
+ res->hasthis = sig->hasthis;
+ res->explicit_this = sig->explicit_this;
+ res->call_convention = sig->call_convention;
+ res->generic_param_count = sig->generic_param_count;
+ return res;
+}
- if (info->native_size & (klass->min_align - 1)) {
- info->native_size += klass->min_align - 1;
- info->native_size &= ~(klass->min_align - 1);
+static MonoMethodHeader*
+inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *ginst)
+{
+ 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;
+ res->gen_params = header->gen_params;
+ res->geninst = ginst;
+ for (i = 0; i < header->num_locals; ++i) {
+ res->locals [i] = mono_class_inflate_generic_type (header->locals [i], ginst);
}
+ return res;
+}
- return klass->marshal_info;
+MonoMethod*
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *ginst)
+{
+ MonoMethod *result;
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+ MonoMethodPInvoke *nmethod = g_new0 (MonoMethodPInvoke, 1);
+ *nmethod = *(MonoMethodPInvoke*)method;
+ result = (MonoMethod*)nmethod;
+ } else {
+ MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1);
+ *nmethod = *(MonoMethodNormal*)method;
+ result = (MonoMethod*)nmethod;
+ if (nmethod->header)
+ nmethod->header = inflate_generic_header (nmethod->header, ginst);
+ }
+ if (ginst->klass)
+ result->klass = ginst->klass;
+ result->signature = mono_class_inflate_generic_signature (method->klass->image, result->signature, ginst);
+ return result;
}
/**
int i, blittable = TRUE, real_size = 0;
guint32 rva;
guint32 packing_size = 0;
+ gboolean explicit_size;
if (class->size_inited)
return;
}
/* Get the real size */
- mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
+ explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
- g_assert ((packing_size & 0xfffffff0) == 0);
- class->packing_size = packing_size;
+ if (explicit_size) {
+ g_assert ((packing_size & 0xfffffff0) == 0);
+ class->packing_size = packing_size;
+ real_size += class->instance_size;
+ }
if (!top) {
+ if (explicit_size && real_size) {
+ class->instance_size = MAX (real_size, class->instance_size);
+ }
class->size_inited = 1;
return;
}
const char *sig;
guint32 cols [MONO_FIELD_SIZE];
int idx = class->field.first + i;
-
+
mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
/* The name is needed for fieldrefs */
class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
g_assert (*sig == 0x06);
class->fields [i].type = mono_metadata_parse_field_type (
m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ if (class->generic_inst) {
+ class->fields [i].type = mono_class_inflate_generic_type (class->fields [i].type, class->generic_inst->data.generic_inst);
+ class->fields [i].type->attrs = cols [MONO_FIELD_FLAGS];
+ }
class->fields [i].parent = class;
class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
blittable = class->element_class->blittable;
}
+
+ /* The def_value of fields is compute lazily during vtable creation */
}
if (class == mono_defaults.string_class)
if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
G_BREAKPOINT ();
}
- mono_class_layout_fields (class);
+ if (explicit_size && real_size) {
+ class->instance_size = MAX (real_size, class->instance_size);
+ }
- if(real_size) {
- if(class->parent)
- real_size += class->parent->instance_size;
+ if (class->gen_params)
+ return;
- class->instance_size = MAX(real_size, class->instance_size);
- }
+ mono_class_layout_fields (class);
}
void
int i;
const int top = class->field.count;
guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
- guint32 pass, passes;
+ guint32 pass, passes, real_size;
+ gboolean gc_aware_layout = FALSE;
+
+ /*
+ * Enable GC aware auto layout: in this mode, reference
+ * fields are grouped together inside objects, increasing collector
+ * performance.
+ * Requires that all classes whose layout is known to native code be annotated
+ * with [StructLayout (LayoutKind.Sequential)]
+ */
+ /* corlib is missing [StructLayout] directives in many places */
+ if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (class->image != mono_defaults.corlib)
+ gc_aware_layout = TRUE;
+ }
/*
* Compute field layout and total size (not considering static fields)
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
-#ifdef GC_AWARE_AUTO_LAYOUT
- passes = 2;
-#else
- passes = 1;
-#endif
+ if (gc_aware_layout)
+ passes = 2;
+ else
+ passes = 1;
+
if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
passes = 1;
+ if (class->parent)
+ real_size = class->parent->instance_size;
+ else
+ real_size = sizeof (MonoObject);
+
for (pass = 0; pass < passes; ++pass) {
for (i = 0; i < top; i++){
int size, align;
if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
-#ifdef GC_AWARE_AUTO_LAYOUT
- /* FIXME: Fix mono_marshal_load_type_info () too */
- if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (gc_aware_layout) {
/*
* We process fields with reference type in the first pass,
* and fields with non-reference type in the second pass.
+ * We use IS_POINTER instead of IS_REFERENCE because in
+ * some internal structures, we store GC_MALLOCed memory
+ * in IntPtr fields...
*/
- if (MONO_TYPE_IS_REFERENCE (class->fields [i].type)) {
+ if (MONO_TYPE_IS_POINTER (class->fields [i].type)) {
if (pass == 1)
continue;
} else {
continue;
}
}
-#endif
+
+ if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
+ (strcmp (class->fields [i].name, "$PRIVATE$") == 0)) {
+ /* This field is a hack inserted by MCS to empty structures */
+ continue;
+ }
size = mono_type_size (class->fields [i].type, &align);
/* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
align = class->packing_size ? MIN (class->packing_size, align): align;
class->min_align = MAX (align, class->min_align);
- class->fields [i].offset = class->instance_size;
+ class->fields [i].offset = real_size;
class->fields [i].offset += align - 1;
class->fields [i].offset &= ~(align - 1);
- class->instance_size = class->fields [i].offset + size;
+ real_size = class->fields [i].offset + size;
}
+
+ class->instance_size = MAX (real_size, class->instance_size);
if (class->instance_size & (class->min_align - 1)) {
class->instance_size += class->min_align - 1;
}
break;
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+ real_size = 0;
for (i = 0; i < top; i++) {
int size, align;
/*
* Calc max size.
*/
- class->instance_size = MAX (class->instance_size, size + class->fields [i].offset);
+ real_size = MAX (real_size, size + class->fields [i].offset);
}
+ class->instance_size = MAX (real_size, class->instance_size);
break;
}
/*
* Compute static field layout and size
*/
- switch (layout) {
- case TYPE_ATTRIBUTE_AUTO_LAYOUT:
- case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
- for (i = 0; i < top; i++){
- int size, align;
-
- if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
- continue;
+ for (i = 0; i < top; i++){
+ int size, align;
- size = mono_type_size (class->fields [i].type, &align);
- class->fields [i].offset = class->class_size;
- class->fields [i].offset += align - 1;
- class->fields [i].offset &= ~(align - 1);
- class->class_size = class->fields [i].offset + size;
-
- }
- break;
- case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
- for (i = 0; i < top; i++){
- int size, align;
-
- /*
- * There must be info about all the fields in a type if it
- * uses explicit layout.
- */
+ if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+ continue;
- if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
- continue;
-
- size = mono_type_size (class->fields [i].type, &align);
- class->fields [i].offset = class->class_size;
- class->fields [i].offset += align - 1;
- class->fields [i].offset &= ~(align - 1);
- class->class_size = class->fields [i].offset + size;
- }
- break;
+ size = mono_type_size (class->fields [i].type, &align);
+ class->fields [i].offset = class->class_size;
+ class->fields [i].offset += align - 1;
+ class->fields [i].offset &= ~(align - 1);
+ class->class_size = class->fields [i].offset + size;
}
}
g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
+ 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 (guint)value;
} else {
++iid;
}
+ mono_loader_unlock ();
+
return iid - 1;
}
static void
-collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray *res)
+collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
{
int i;
MonoClass *ic;
for (i = 0; i < klass->interface_count; i++) {
ic = klass->interfaces [i];
- g_ptr_array_add (res, ic);
+ if (*res == NULL)
+ *res = g_ptr_array_new ();
+ g_ptr_array_add (*res, ic);
collect_implemented_interfaces_aux (ic, res);
}
}
-static GPtrArray*
+static inline GPtrArray*
collect_implemented_interfaces (MonoClass *klass)
{
- GPtrArray *res = g_ptr_array_new ();
+ GPtrArray *res = NULL;
- collect_implemented_interfaces_aux (klass, res);
+ collect_implemented_interfaces_aux (klass, &res);
return res;
}
class->interface_offsets [i] = -1;
ifaces = collect_implemented_interfaces (class);
- for (i = 0; i < ifaces->len; ++i) {
- ic = g_ptr_array_index (ifaces, i);
- class->interface_offsets [ic->interface_id] = cur_slot;
- cur_slot += ic->method.count;
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ ic = g_ptr_array_index (ifaces, i);
+ class->interface_offsets [ic->interface_id] = cur_slot;
+ cur_slot += ic->method.count;
+ }
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
for (k = class->parent; k ; k = k->parent) {
ifaces = collect_implemented_interfaces (k);
- for (i = 0; i < ifaces->len; ++i) {
- ic = g_ptr_array_index (ifaces, i);
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ ic = g_ptr_array_index (ifaces, i);
- if (class->interface_offsets [ic->interface_id] == -1) {
- int io = k->interface_offsets [ic->interface_id];
+ if (class->interface_offsets [ic->interface_id] == -1) {
+ int io = k->interface_offsets [ic->interface_id];
- g_assert (io >= 0);
+ g_assert (io >= 0);
- class->interface_offsets [ic->interface_id] = io;
+ class->interface_offsets [ic->interface_id] = io;
+ }
}
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
}
+
+ if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
+ class->interface_offsets [class->interface_id] = cur_slot;
+
return cur_slot;
}
MonoMethod **vtable;
int i, max_vtsize = 0, max_iid, cur_slot = 0;
GPtrArray *ifaces;
- MonoGHashTable *override_map;
+ MonoGHashTable *override_map = NULL;
/* setup_vtable() must be called only once on the type */
if (class->interface_offsets) {
}
ifaces = collect_implemented_interfaces (class);
- for (i = 0; i < ifaces->len; i++) {
- MonoClass *ic = g_ptr_array_index (ifaces, i);
- max_vtsize += ic->method.count;
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; i++) {
+ MonoClass *ic = g_ptr_array_index (ifaces, i);
+ max_vtsize += ic->method.count;
+ }
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
if (class->parent) {
max_vtsize += class->parent->vtable_size;
if (class->parent && class->parent->vtable_size)
memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
- override_map = mono_g_hash_table_new (NULL, NULL);
-
/* override interface methods */
for (i = 0; i < onum; i++) {
MonoMethod *decl = overrides [i*2];
dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
vtable [dslot] = overrides [i*2 + 1];
vtable [dslot]->slot = dslot;
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
+
mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
}
}
for (k = class; k ; k = k->parent) {
+ int nifaces = 0;
ifaces = collect_implemented_interfaces (k);
- for (i = 0; i < ifaces->len; i++) {
+ if (ifaces)
+ nifaces = ifaces->len;
+ for (i = 0; i < nifaces; i++) {
int j, l, io;
ic = g_ptr_array_index (ifaces, i);
}
}
}
- g_ptr_array_free (ifaces, TRUE);
+ if (ifaces)
+ g_ptr_array_free (ifaces, TRUE);
}
for (i = 0; i < class->method.count; ++i) {
mono_metadata_signature_equal (cm->signature, m1->signature)) {
slot = k->methods [j]->slot;
g_assert (cm->slot < max_vtsize);
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
mono_g_hash_table_insert (override_map, m1, cm);
break;
}
if (cm->slot < 0)
cm->slot = cur_slot++;
- if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
+ if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count)
vtable [cm->slot] = cm;
}
g_assert (decl->slot != -1);
vtable [decl->slot] = overrides [i*2 + 1];
overrides [i * 2 + 1]->slot = decl->slot;
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
}
}
* If a method occupies more than one place in the vtable, and it is
* overriden, then change the other occurances too.
*/
- for (i = 0; i < max_vtsize; ++i)
- if (vtable [i]) {
- MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
- if (cm)
- vtable [i] = cm;
- }
- mono_g_hash_table_destroy (override_map);
+ if (override_map) {
+ for (i = 0; i < max_vtsize; ++i)
+ if (vtable [i]) {
+ MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
+ if (cm)
+ vtable [i] = cm;
+ }
+ mono_g_hash_table_destroy (override_map);
+ }
class->vtable_size = cur_slot;
class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
if (class->inited)
return;
+ /*g_print ("Init class %s\n", class->name);*/
+
+ /* We do everything inside the lock to prevent races */
+ mono_loader_lock ();
+
+ if (class->inited) {
+ mono_loader_unlock ();
+ /* Somebody might have gotten in before us */
+ return;
+ }
+
if (class->init_pending) {
/* this indicates a cyclic dependency */
g_error ("pending init %s.%s\n", class->name_space, class->name);
class_compute_field_layout (class);
/* initialize method pointers */
- class->methods = g_new (MonoMethod*, class->method.count);
- for (i = 0; i < class->method.count; ++i)
- class->methods [i] = mono_get_method (class->image,
- MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
+ if (class->rank) {
+ MonoMethod *ctor;
+ MonoMethodSignature *sig;
+ class->method.count = class->rank > 1? 2: 1;
+ 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->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 [0] = ctor;
+ if (class->rank > 1) {
+ sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ sig->pinvoke = TRUE;
+ for (i = 0; i < class->rank * 2; ++i)
+ sig->params [i] = &mono_defaults.int32_class->byval_arg;
+
+ ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
+ 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 [1] = ctor;
+ }
+ } else {
+ if (!class->generic_inst && !class->methods) {
+ class->methods = g_new (MonoMethod*, class->method.count);
+ for (i = 0; i < class->method.count; ++i) {
+ class->methods [i] = mono_get_method (class->image,
+ MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
+ }
+ }
+ }
init_properties (class);
init_events (class);
* we have to setup them for interfaces, too.
*/
setup_interface_offsets (class, 0);
+ mono_loader_unlock ();
return;
}
class->has_finalize = 1;
}
+ mono_loader_unlock ();
+
if (mono_debugger_class_init_func)
mono_debugger_class_init_func (class);
}
-/*
- * Compute a relative numbering of the class hierarchy as described in
- * "Java for Large-Scale Scientific Computations?"
- */
-static void
-mono_compute_relative_numbering (MonoClass *class, int *c)
-{
- GList *s;
-
- (*c)++;
-
- class->baseval = *c;
-
- for (s = class->subclasses; s; s = s->next)
- mono_compute_relative_numbering ((MonoClass *)s->data, c);
-
- class->diffval = *c - class->baseval;
-}
-
void
mono_class_setup_mono_type (MonoClass *class)
{
class->blittable = TRUE;
}
break;
+ case 'T':
+ if (!strcmp (name, "TypedReference")) {
+ t = MONO_TYPE_TYPEDBYREF;
+ class->blittable = TRUE;
+ }
+ break;
case 'V':
if (!strcmp (name, "Void")) {
t = MONO_TYPE_VOID;
}
if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
- int rnum = 0;
class->parent = parent;
if (!parent)
g_assert_not_reached (); /* FIXME */
+ if (parent->generic_inst && !parent->name) {
+ /*
+ * If the parent is a generic instance, we may get
+ * called before it is fully initialized, especially
+ * before it has its name.
+ */
+ return;
+ }
+
class->marshalbyref = parent->marshalbyref;
class->contextbound = parent->contextbound;
class->delegate = parent->delegate;
class->valuetype = class->enumtype = 1;
}
/*class->enumtype = class->parent->enumtype; */
- class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
- mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
mono_class_setup_supertypes (class);
} else {
class->parent = NULL;
guint icount = 0;
MonoClass **interfaces;
- if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
+ mono_loader_lock ();
+
+ if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
+ mono_loader_unlock ();
return class;
+ }
g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
class->cast_class = class->element_class = class;
- /*g_print ("Init class %s\n", name);*/
+ /*g_print ("Load class %s\n", name);*/
mono_class_setup_parent (class, parent);
if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
class->nested_in = mono_class_create_from_typedef (image, type_token);
+ class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount);
+ class->num_gen_params = icount;
+
+ mono_loader_unlock ();
+
+ return class;
+}
+
+static char*
+get_instantiation_name (const char *name, MonoGenericInst *ginst)
+{
+ GString *res = g_string_new (name);
+ const char *p;
+ int i;
+ MonoClass *argclass;
+
+ p = strchr (name, '<');
+ if (p) {
+ g_string_truncate (res, (p - name) + 1);
+ } else {
+ g_string_append_c (res, '<');
+ }
+ for (i = 0; i < ginst->type_argc; ++i) {
+ if (i > 0)
+ g_string_append_c (res, ',');
+ argclass = mono_class_from_mono_type (ginst->type_argv [i]);
+ g_string_append (res, argclass->name);
+ }
+ g_string_append_c (res, '>');
+ return g_string_free (res, FALSE);
+}
+
+MonoClass*
+mono_class_create_from_generic (MonoImage *image, MonoType *gtype)
+{
+ MonoClass *gklass = mono_class_from_mono_type (gtype->data.generic_inst->generic_type);
+ MonoClass *class;
+
+ mono_class_init (gklass);
+
+ class = g_new0 (MonoClass, 1);
+ class->name_space = gklass->name_space;
+ class->image = image;
+ class->flags = gklass->flags;
+
+ class->generic_inst = gtype;
+
+ class->cast_class = class->element_class = class;
+
+ return class;
+}
+
+void
+mono_class_initialize_generic (MonoClass *class, gboolean inflate_methods)
+{
+ MonoGenericInst *ginst = class->generic_inst->data.generic_inst;
+ MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
+
+ if (class->name)
+ return;
+
+ class->name = get_instantiation_name (gklass->name, ginst);
+
+ if (inflate_methods) {
+ int i;
+
+ mono_class_setup_parent (class, gklass->parent);
+ mono_class_setup_mono_type (class);
+
+ class->field = gklass->field;
+ class->method = gklass->method;
+ class->methods = g_new0 (MonoMethod *, class->method.count);
+ for (i = 0; i < class->method.count; i++)
+ class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
+ }
+
+ g_hash_table_insert (class->image->generics_cache, ginst->generic_type, class);
+}
+
+MonoClass*
+mono_class_from_generic (MonoType *gtype, gboolean inflate_methods)
+{
+ MonoGenericInst *ginst = gtype->data.generic_inst;
+ MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type);
+ MonoClass *class;
+ MonoImage *image;
+
+ if (ginst->klass)
+ return ginst->klass;
+
+ mono_loader_lock ();
+
+ image = gklass->image;
+ if ((class = g_hash_table_lookup (image->generics_cache, gtype))) {
+ mono_loader_unlock ();
+ return class;
+ }
+
+ mono_class_init (gklass);
+
+ class = g_malloc0 (sizeof (MonoClass));
+ class->name_space = gklass->name_space;
+ class->name = get_instantiation_name (gklass->name, ginst);
+ class->image = image;
+ class->flags = gklass->flags;
+
+ class->generic_inst = gtype;
+
+ class->cast_class = class->element_class = class;
+
+ if (inflate_methods) {
+ int i;
+
+ mono_class_setup_parent (class, gklass->parent);
+ mono_class_setup_mono_type (class);
+
+ class->field = gklass->field;
+ class->method = gklass->method;
+ class->methods = g_new0 (MonoMethod *, class->method.count);
+ for (i = 0; i < class->method.count; i++)
+ class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
+ }
+
+ g_hash_table_insert (image->generics_cache, gtype, class);
+
+ mono_loader_unlock ();
+
return class;
}
+MonoClass *
+mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
+{
+ MonoClass *klass, **ptr;
+ int count, pos, i;
+
+ if (param->pklass)
+ return param->pklass;
+
+ klass = param->pklass = g_new0 (MonoClass, 1);
+
+ for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
+ ;
+
+ pos = 0;
+ if ((count > 0) && !(param->constraints [0]->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ klass->parent = param->constraints [0];
+ pos++;
+ } else
+ klass->parent = mono_defaults.object_class;
+
+ if (count - pos > 0) {
+ int j;
+
+ 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];
+ klass->method.count += param->constraints [i]->method.count;
+ }
+
+ klass->methods = g_new0 (MonoMethod *, klass->method.count);
+ for (i = pos; i < count; i++) {
+ MonoClass *iface = klass->interfaces [i - pos];
+ for (j = 0; j < iface->method.count; j++)
+ klass->methods [klass->method.last++] = iface->methods [j];
+ }
+ }
+
+ klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+ klass->name_space = "";
+ klass->image = image;
+ klass->cast_class = klass->element_class = klass;
+ klass->enum_basetype = &klass->element_class->byval_arg;
+ klass->flags = TYPE_ATTRIBUTE_INTERFACE;
+
+ 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;
+
+ mono_class_init (klass);
+
+ return klass;
+}
+
+static MonoClass *
+my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
+{
+ MonoClass *klass;
+
+ if (param->pklass)
+ return param->pklass;
+
+ klass = g_new0 (MonoClass, 1);
+
+ klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+ klass->name_space = "";
+ klass->image = mono_defaults.corlib;
+ klass->cast_class = klass->element_class = klass;
+ klass->enum_basetype = &klass->element_class->byval_arg;
+ klass->flags = TYPE_ATTRIBUTE_INTERFACE;
+
+ 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;
+
+ mono_class_init (klass);
+
+ return klass;
+}
+
MonoClass *
mono_ptr_class_get (MonoType *type)
{
MonoClass *el_class;
static GHashTable *ptr_hash = NULL;
+ mono_loader_lock ();
+
if (!ptr_hash)
- ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ptr_hash = g_hash_table_new (NULL, NULL);
el_class = mono_class_from_mono_type (type);
- if ((result = g_hash_table_lookup (ptr_hash, el_class)))
+ if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
+ mono_loader_unlock ();
return result;
+ }
result = g_new0 (MonoClass, 1);
result->parent = NULL; /* no parent for PTR types */
result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
/* Can pointers get boxed? */
result->instance_size = sizeof (gpointer);
- /*
- * baseval, diffval: need them to allow casting ?
- */
result->cast_class = result->element_class = el_class;
result->enum_basetype = &result->element_class->byval_arg;
result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
result->this_arg.byref = TRUE;
+ mono_class_setup_supertypes (result);
+
g_hash_table_insert (ptr_hash, el_class, result);
+ mono_loader_unlock ();
+
return result;
}
MonoClass *result;
static GHashTable *ptr_hash = NULL;
+ mono_loader_lock ();
+
if (!ptr_hash)
- ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ptr_hash = g_hash_table_new (NULL, NULL);
- if ((result = g_hash_table_lookup (ptr_hash, sig)))
+ if ((result = g_hash_table_lookup (ptr_hash, sig))) {
+ mono_loader_unlock ();
return result;
+ }
result = g_new0 (MonoClass, 1);
result->parent = NULL; /* no parent for PTR types */
result->flags = TYPE_ATTRIBUTE_CLASS; // | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
/* Can pointers get boxed? */
result->instance_size = sizeof (gpointer);
- /*
- * baseval, diffval: need them to allow casting ?
- */
result->cast_class = result->element_class = result;
result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
result->this_arg.byref = TRUE;
result->enum_basetype = &result->element_class->byval_arg;
+ mono_class_setup_supertypes (result);
+
g_hash_table_insert (ptr_hash, sig, result);
+ mono_loader_unlock ();
+
return result;
}
{
switch (type->type) {
case MONO_TYPE_OBJECT:
- return mono_defaults.object_class;
+ return type->data.klass? type->data.klass: mono_defaults.object_class;
case MONO_TYPE_VOID:
- return mono_defaults.void_class;
+ return type->data.klass? type->data.klass: mono_defaults.void_class;
case MONO_TYPE_BOOLEAN:
- return mono_defaults.boolean_class;
+ return type->data.klass? type->data.klass: mono_defaults.boolean_class;
case MONO_TYPE_CHAR:
- return mono_defaults.char_class;
+ return type->data.klass? type->data.klass: mono_defaults.char_class;
case MONO_TYPE_I1:
- return mono_defaults.sbyte_class;
+ return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
case MONO_TYPE_U1:
- return mono_defaults.byte_class;
+ return type->data.klass? type->data.klass: mono_defaults.byte_class;
case MONO_TYPE_I2:
- return mono_defaults.int16_class;
+ return type->data.klass? type->data.klass: mono_defaults.int16_class;
case MONO_TYPE_U2:
- return mono_defaults.uint16_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint16_class;
case MONO_TYPE_I4:
- return mono_defaults.int32_class;
+ return type->data.klass? type->data.klass: mono_defaults.int32_class;
case MONO_TYPE_U4:
- return mono_defaults.uint32_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint32_class;
case MONO_TYPE_I:
- return mono_defaults.int_class;
+ return type->data.klass? type->data.klass: mono_defaults.int_class;
case MONO_TYPE_U:
- return mono_defaults.uint_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint_class;
case MONO_TYPE_I8:
- return mono_defaults.int64_class;
+ return type->data.klass? type->data.klass: mono_defaults.int64_class;
case MONO_TYPE_U8:
- return mono_defaults.uint64_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint64_class;
case MONO_TYPE_R4:
- return mono_defaults.single_class;
+ return type->data.klass? type->data.klass: mono_defaults.single_class;
case MONO_TYPE_R8:
- return mono_defaults.double_class;
+ return type->data.klass? type->data.klass: mono_defaults.double_class;
case MONO_TYPE_STRING:
- return mono_defaults.string_class;
+ return type->data.klass? type->data.klass: mono_defaults.string_class;
case MONO_TYPE_TYPEDBYREF:
- return mono_defaults.typed_reference_class;
+ return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
case MONO_TYPE_ARRAY:
- return mono_array_class_get (type->data.array->type, type->data.array->rank);
+ return mono_array_class_get (type->data.array->eklass, type->data.array->rank);
case MONO_TYPE_PTR:
return mono_ptr_class_get (type->data.type);
case MONO_TYPE_FNPTR:
return mono_fnptr_class_get (type->data.method);
case MONO_TYPE_SZARRAY:
- return mono_array_class_get (type->data.type, 1);
+ return mono_array_class_get (type->data.klass, 1);
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
return type->data.klass;
-
case MONO_TYPE_GENERICINST:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_GENERICINST");
- g_assert_not_reached ();
-
+ return mono_class_from_generic (type, TRUE);
case MONO_TYPE_VAR:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_VAR");
- g_assert_not_reached ();
-
+ return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
case MONO_TYPE_MVAR:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_MVAR");
- g_assert_not_reached ();
-
+ return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
default:
g_warning ("implement me 0x%02x\n", type->type);
g_assert_not_reached ();
switch (type->type) {
case MONO_TYPE_ARRAY:
- class = mono_array_class_get (type->data.array->type, type->data.array->rank);
+ class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
break;
case MONO_TYPE_SZARRAY:
- class = mono_array_class_get (type->data.type, 1);
+ class = mono_array_class_get (type->data.klass, 1);
break;
case MONO_TYPE_PTR:
class = mono_class_from_mono_type (type->data.type);
break;
}
- mono_metadata_free_type (type);
-
return class;
}
/**
* mono_array_class_get:
- * @element_type: element type
+ * @element_class: element class
* @rank: the dimension of the array class
*
* Returns: a class object describing the array with element type @element_type and
* dimension @rank.
*/
MonoClass *
-mono_array_class_get (MonoType *element_type, guint32 rank)
+mono_array_class_get (MonoClass *eclass, guint32 rank)
{
- MonoClass *eclass;
MonoImage *image;
MonoClass *class;
MonoClass *parent = NULL;
- GSList *list;
- int rnum = 0, nsize;
+ GSList *list, *rootlist;
+ int nsize;
char *name;
+ gboolean corlib_type = FALSE;
- eclass = mono_class_from_mono_type (element_type);
g_assert (rank <= 255);
- parent = mono_defaults.array_class;
-
- if (!parent->inited)
- mono_class_init (parent);
-
image = eclass->image;
- if ((list = g_hash_table_lookup (image->array_cache, element_type))) {
+ mono_loader_lock ();
+
+ if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
for (; list; list = list->next) {
class = list->data;
- if (class->rank == rank)
+ if (class->rank == rank) {
+ mono_loader_unlock ();
return class;
+ }
}
}
-
- class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
+
+ /* for the building corlib use System.Array from it */
+ if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
+ parent = mono_class_from_name (image, "System", "Array");
+ corlib_type = TRUE;
+ } else {
+ parent = mono_defaults.array_class;
+ if (!parent->inited)
+ mono_class_init (parent);
+ }
+
+ class = g_malloc0 (sizeof (MonoClass));
class->image = image;
class->name_space = eclass->name_space;
name [nsize + rank + 1] = 0;
class->name = 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 | TYPE_ATTRIBUTE_LAYOUT_MASK |
- TYPE_ATTRIBUTE_STRING_FORMAT_MASK));
+ (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
class->parent = parent;
class->instance_size = mono_class_instance_size (class->parent);
class->class_size = 0;
- class->vtable_size = parent->vtable_size;
- class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
- mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
mono_class_setup_supertypes (class);
class->rank = rank;
MonoArrayType *at = g_new0 (MonoArrayType, 1);
class->byval_arg.type = MONO_TYPE_ARRAY;
class->byval_arg.data.array = at;
- at->type = &eclass->byval_arg;
+ at->eklass = eclass;
at->rank = rank;
/* FIXME: complete.... */
} else {
/* FIXME: this is not correct. the lbound could be >0 */
class->byval_arg.type = MONO_TYPE_SZARRAY;
- class->byval_arg.data.type = &eclass->byval_arg;
+ class->byval_arg.data.klass = eclass;
}
class->this_arg = class->byval_arg;
class->this_arg.byref = 1;
+ if (corlib_type) {
+ class->inited = 1;
+ }
+
+ list = g_slist_append (rootlist, class);
+ g_hash_table_insert (image->array_cache, eclass, list);
+
+ mono_loader_unlock ();
- list = g_slist_append (list, class);
- g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list);
return class;
}
*/
gint32
mono_class_instance_size (MonoClass *klass)
-{
-
+{
if (!klass->size_inited)
mono_class_init (klass);
return klass->instance_size;
}
-/**
- * mono_class_native_size:
- * @klass: a class
- *
- * Returns: the native size of an object instance (when marshaled
- * to unmanaged code)
- */
-gint32
-mono_class_native_size (MonoClass *klass, guint32 *align)
-{
-
- if (!klass->marshal_info)
- mono_marshal_load_type_info (klass);
-
- if (align)
- *align = klass->min_align;
-
- return klass->marshal_info->native_size;
-}
-
/**
* mono_class_min_align:
* @klass: a class
*/
gint32
mono_class_min_align (MonoClass *klass)
-{
-
+{
if (!klass->size_inited)
mono_class_init (klass);
*/
gint32
mono_class_data_size (MonoClass *klass)
-{
-
+{
if (!klass->inited)
mono_class_init (klass);
return NULL;
}
-static MonoImage*
-load_file_for_image (MonoImage *image, int fileidx)
-{
- char *base_dir, *name;
- MonoImage *res;
- MonoTableInfo *t = &image->tables [MONO_TABLE_FILE];
- const char *fname;
- guint32 fname_id;
-
- if (fileidx < 1 || fileidx > t->rows)
- return NULL;
- fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME);
- fname = mono_metadata_string_heap (image, fname_id);
- base_dir = g_path_get_dirname (image->name);
- name = g_build_filename (base_dir, fname, NULL);
- res = mono_image_open (name, NULL);
- if (res) {
- int i;
- t = &res->tables [MONO_TABLE_MODULEREF];
- //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly);
- res->assembly = image->assembly;
- for (i = 0; i < t->rows; ++i) {
- if (res->modules [i] && !res->modules [i]->assembly)
- res->modules [i]->assembly = image->assembly;
- }
- mono_image_load_references (image, NULL);
- }
- g_free (name);
- g_free (base_dir);
- return res;
-}
-
static MonoClass*
return_nested_in (MonoClass *class, char *nested) {
MonoClass *found;
{
GHashTable *nspace_table;
MonoImage *loaded_image;
- guint32 token;
+ guint32 token = 0;
MonoClass *class;
char *nested;
char buf [1024];
name = buf;
}
+ mono_loader_lock ();
+
nspace_table = g_hash_table_lookup (image->name_cache, name_space);
-
- if (!nspace_table || !(token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)))) {
+
+ if (nspace_table)
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
+
+ mono_loader_unlock ();
+
+ if (!token)
+ return NULL;
+
+ if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
guint32 cols [MONO_EXP_TYPE_SIZE];
- int i;
-
- for (i = 0; i < t->rows; ++i) {
- const char *ename, *enspace;
- mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
- ename = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
- enspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
-
- if (strcmp (name, ename) == 0 && strcmp (name_space, enspace) == 0) {
- guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
- if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
- loaded_image = load_file_for_image (image, impl >> IMPLEMENTATION_BITS);
- if (!loaded_image)
- return NULL;
- class = mono_class_from_name (loaded_image, name_space, name);
- if (nested)
- return return_nested_in (class, nested);
- return class;
- } else {
- g_error ("not yet implemented");
- }
- }
+ guint32 idx, impl;
+
+ idx = mono_metadata_token_index (token);
+
+ mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
+
+ impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
+ if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
+ loaded_image = mono_assembly_load_module (image->assembly, impl >> IMPLEMENTATION_BITS);
+ if (!loaded_image)
+ return NULL;
+ class = mono_class_from_name (loaded_image, name_space, name);
+ if (nested)
+ return return_nested_in (class, nested);
+ return class;
+ } else {
+ g_error ("not yet implemented");
}
- /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
- return NULL;
}
token = MONO_TOKEN_TYPE_DEF | token;
return TRUE;
}
} else {
- /*
- * klass->baseval is 0 for interfaces
- */
- if (klass->baseval && ((klass->baseval - klassc->baseval) <= klassc->diffval))
+ if (!(klass->flags & TYPE_ATTRIBUTE_INTERFACE) && mono_class_has_parent (klass, klassc))
return TRUE;
}
+
+ /*
+ * MS.NET thinks interfaces are a subclass of Object, so we think it as
+ * well.
+ */
+ if (klassc == mono_defaults.object_class)
+ return TRUE;
return FALSE;
}
+gboolean
+mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
+{
+ if (!klass->inited)
+ mono_class_init (klass);
+
+ if (!oklass->inited)
+ mono_class_init (oklass);
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ 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;
+
+ eclass = klass->cast_class;
+ eoclass = oklass->cast_class;
+
+
+ /*
+ * a is b does not imply a[] is b[] when a is a valuetype, and
+ * b is a reference type.
+ */
+
+ if (eoclass->valuetype) {
+ if ((eclass == mono_defaults.enum_class) ||
+ (eclass == mono_defaults.enum_class->parent) ||
+ (eclass == mono_defaults.object_class))
+ return FALSE;
+ }
+
+ return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
+ }
+ else
+ if (klass == mono_defaults.object_class)
+ return TRUE;
+
+ return mono_class_has_parent (oklass, klass);
+}
+
+/*
+ * mono_class_needs_cctor_run:
+ *
+ * Determines whenever the class has a static constructor and whenever it
+ * needs to be called when executing CALLER.
+ */
+gboolean
+mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
+{
+ int i;
+ MonoMethod *method;
+
+ for (i = 0; i < klass->method.count; ++i) {
+ method = klass->methods [i];
+ if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
+ (strcmp (".cctor", method->name) == 0)) {
+ if (caller == method)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/*
* Returns the nnumber of bytes an element of type klass
* uses when stored into an array.
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
return sizeof (gpointer);
case MONO_TYPE_I8:
case MONO_TYPE_U8:
class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
mono_class_init (class);
if (handle_class)
- *handle_class = mono_defaults.fieldhandle_class;
+ *handle_class = mono_defaults.fieldhandle_class;
return mono_class_get_field (class, token);
}
- case MONO_TOKEN_METHOD_DEF:
- case MONO_TOKEN_MEMBER_REF:
+ case MONO_TOKEN_METHOD_DEF: {
+ MonoMethod *meth;
+ meth = mono_get_method (image, token, NULL);
+ if (handle_class)
+ *handle_class = mono_defaults.methodhandle_class;
+ return meth;
+ }
+ case MONO_TOKEN_MEMBER_REF: {
+ guint32 cols [MONO_MEMBERREF_SIZE];
+ const char *sig;
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
+ sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
+ mono_metadata_decode_blob_size (sig, &sig);
+ if (*sig == 0x6) { /* it's a field */
+ MonoClass *klass;
+ MonoClassField *field;
+ field = mono_field_from_token (image, token, &klass);
+ if (handle_class)
+ *handle_class = mono_defaults.fieldhandle_class;
+ return field;
+ } else {
+ MonoMethod *meth;
+ meth = mono_get_method (image, token, NULL);
+ if (handle_class)
+ *handle_class = mono_defaults.methodhandle_class;
+ return meth;
+ }
+ }
default:
g_warning ("Unknown token 0x%08x in ldtoken", token);
break;
{
return lookup_dynamic (image, token);
}
+
+
+