MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
+gboolean mono_align_small_structs = FALSE;
/* Statistics */
guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
The defacto behavior is that it's just a typedef in disguise.
*/
/* a typedef in disguise */
- res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
+ res = mono_class_from_name_checked (image, nspace, name, error);
goto done;
case MONO_RESOLUTION_SCOPE_MODULEREF:
module = mono_image_load_module (image, idx);
if (module)
- res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
+ res = mono_class_from_name_checked (module, nspace, name, error);
goto done;
case MONO_RESOLUTION_SCOPE_TYPEREF: {
return NULL;
}
- res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
+ res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
done:
/* Generic case, should be avoided for when a better error is possible. */
if (!res && mono_error_ok (error)) {
- char *name = mono_class_name_from_token (image, type_token);
- char *assembly = mono_assembly_name_from_token (image, type_token);
- mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
+ if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
+ mono_error_set_from_loader_error (error);
+ } else {
+ char *name = mono_class_name_from_token (image, type_token);
+ char *assembly = mono_assembly_name_from_token (image, type_token);
+ mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
+ }
}
+ g_assert (!mono_loader_get_last_error ());
return res;
}
case MONO_TYPE_VOID:
//case MONO_TYPE_TYPEDBYREF:
return FALSE;
+ default:
+ return TRUE;
}
- return TRUE;
}
static MonoType*
return mono_class_inflate_generic_method_full (method, NULL, context);
}
+MonoMethod *
+mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
+{
+ return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
+}
+
/**
* mono_class_inflate_generic_method_full:
*
else if (iresult->declaring->klass->generic_class)
iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
}
+ /* This can happen with some callers like mono_object_get_virtual_method () */
+ if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
+ iresult->context.class_inst = NULL;
cached = mono_method_inflated_lookup (iresult, FALSE);
if (cached) {
return type->data.array->eklass->exception_type;
case MONO_TYPE_GENERICINST:
return mono_generic_class_get_class (type->data.generic_class)->exception_type;
+ default:
+ return FALSE;
}
- return FALSE;
}
/*
explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
if (explicit_size) {
- if ((packing_size & 0xfffffff0) != 0) {
- char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
+ if ((packing_size & 0xffffff00) != 0) {
+ char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
return;
}
return;
}
- if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
blittable = FALSE;
/* Prevent infinite loops if the class references itself */
MonoType*
mono_type_get_basic_type_from_generic (MonoType *type)
{
- /* When we do generic sharing we let type variables stand for reference types. */
- if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
+ /* When we do generic sharing we let type variables stand for reference/primitive types. */
+ if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
+ (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
return &mono_defaults.object_class->byval_arg;
return type;
}
+static gboolean
+type_has_references (MonoClass *klass, MonoType *ftype)
+{
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ return TRUE;
+ if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
+ MonoGenericParam *gparam = ftype->data.generic_param;
+
+ if (gparam->gshared_constraint)
+ return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
+ }
+ return FALSE;
+}
+
/*
* mono_class_layout_fields:
* @class: a class
if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
class->has_references = TRUE;
}
}
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
class->has_static_refs = TRUE;
}
}
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
class->has_static_refs = TRUE;
else
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
if (gc_aware_layout) {
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (pass == 1)
continue;
} else {
/* if the field has managed references, we need to force-align it
* see bug #77788
*/
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
align = MAX (align, sizeof (gpointer));
class->min_align = MAX (align, class->min_align);
field->offset += sizeof (MonoObject);
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (field->offset % sizeof (gpointer)) {
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
}
if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
/*
+ * This leads to all kinds of problems with nested structs, so only
+ * enable it when a MONO_DEBUG property is set.
+ *
* For small structs, set min_align to at least the struct size to improve
* performance, and 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));
+ if (mono_align_small_structs) {
+ if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+ class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+ }
}
mono_memory_barrier ();
for (i = 0; i < class->interface_count; i++)
setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
} else {
+ MonoError error;
+
count = class->method.count;
methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
for (i = 0; i < count; ++i) {
int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
- methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
+ methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
+ if (!methods [i]) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
+ mono_error_cleanup (&error);
+ }
}
}
MonoMethod*
mono_class_get_method_by_index (MonoClass *class, int index)
{
+ MonoError error;
/* Avoid calling setup_methods () if possible */
if (class->generic_class && !class->methods) {
MonoClass *gklass = class->generic_class->container_class;
MonoMethod *m;
- m = mono_class_inflate_generic_method_full (
- gklass->methods [index], class, mono_class_get_context (class));
+ m = mono_class_inflate_generic_method_full_checked (
+ gklass->methods [index], class, mono_class_get_context (class), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/*
* If setup_methods () is called later for this class, no duplicates are created,
* since inflate_generic_method guarantees that only one instance of a method
for (i = 0; i < gklass->method.count; ++i) {
if (gklass->methods [i] == method) {
- if (class->methods)
+ if (class->methods) {
return class->methods [i];
- else
- return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
+ } else {
+ MonoError error;
+ MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
+ return result;
+ }
}
}
}
if (class->generic_class) {
+ MonoError error;
MonoClass *gklass = class->generic_class->container_class;
mono_class_setup_vtable (gklass);
m = gklass->vtable [offset];
- m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
+ m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
} else {
mono_class_setup_vtable (class);
if (class->exception_type)
properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
for (i = 0; i < gklass->ext->property.count; i++) {
+ MonoError error;
MonoProperty *prop = &properties [i];
*prop = gklass->ext->properties [i];
if (prop->get)
- prop->get = mono_class_inflate_generic_method_full (
- prop->get, class, mono_class_get_context (class));
+ prop->get = mono_class_inflate_generic_method_full_checked (
+ prop->get, class, mono_class_get_context (class), &error);
if (prop->set)
- prop->set = mono_class_inflate_generic_method_full (
- prop->set, class, mono_class_get_context (class));
+ prop->set = mono_class_inflate_generic_method_full_checked (
+ prop->set, class, mono_class_get_context (class), &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
prop->parent = class;
}
mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
- if (class->image->uncompressed_metadata)
+ if (class->image->uncompressed_metadata) {
+ MonoError error;
/* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
- method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
- else
+ method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow this error */
+ } else {
method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+ }
switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
case METHOD_SEMANTIC_SETTER:
retval = g_new0 (MonoMethod*, count + 1);
count = 0;
- for (om = methods, count = 0; *om; ++om, ++count)
- retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
+ for (om = methods, count = 0; *om; ++om, ++count) {
+ MonoError error;
+ retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ }
return retval;
}
context = mono_class_get_context (class);
for (i = 0; i < count; i++) {
+ MonoError error;
MonoEvent *event = &events [i];
MonoEvent *gevent = &gklass->ext->events [i];
+ mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
+
event->parent = class;
event->name = gevent->name;
- event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
- event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
- event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
+ event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+
#ifndef MONO_SMALL_CONFIG
event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
#endif
mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
- if (class->image->uncompressed_metadata)
+ if (class->image->uncompressed_metadata) {
+ MonoError error;
/* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
- method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
- else
+ method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow this error */
+ } else {
method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+ }
switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
case METHOD_SEMANTIC_ADD_ON:
find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
{
int i = find_interface (num_ifaces, interfaces_full, ic);
- if (ic >= 0)
+ if (i >= 0)
return interface_offsets_full [i];
return -1;
}
* mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
* means we have to overwrite those when called from other places (#4440).
*/
- if (class->interfaces_packed && !overwrite) {
- g_assert (class->interface_offsets_count == interface_offsets_count);
+ if (class->interfaces_packed) {
+ if (!overwrite)
+ g_assert (class->interface_offsets_count == interface_offsets_count);
} else {
uint8_t *bitmap;
int bsize;
}
static gboolean
-check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
+check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
+{
MonoMethodSignature *cmsig, *imsig;
if (strcmp (im->name, cm->name) == 0) {
if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
return FALSE;
}
TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
- /* CAS - SecurityAction.InheritanceDemand on interface */
- if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, im);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
}
TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
- /* CAS - SecurityAction.InheritanceDemand on interface */
- if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, im);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
int i, max_vtsize = 0, max_iid, cur_slot = 0;
GPtrArray *ifaces = NULL;
GHashTable *override_map = NULL;
- gboolean security_enabled = mono_security_enabled ();
MonoMethod *cm;
- gpointer class_iter;
#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
int first_non_interface_slot;
#endif
// otherwise look for a matching method
if (override_im == NULL) {
int cm_index;
- gpointer iter;
MonoMethod *cm;
// First look for a suitable method among the class methods
- iter = NULL;
for (l = virt_methods; l; l = l->next) {
cm = l->data;
TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
- if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
+ if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
vtable [im_slot] = cm;
/* Why do we need this? */
MonoMethod *cm = parent->vtable [cm_index];
TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
- if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
+ if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
vtable [im_slot] = cm;
/* Why do we need this? */
}
TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
- class_iter = NULL;
for (l = virt_methods; l; l = l->next) {
cm = l->data;
/*
if (!strcmp(cm->name, m1->name) &&
mono_metadata_signature_equal (cmsig, m1sig)) {
- /* CAS - SecurityAction.InheritanceDemand */
- if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, m1);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, m1);
MonoClass *gklass;
int i;
+ if (!method->klass->generic_class) {
+ g_assert (method->is_inflated);
+ return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
+ }
+
/* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
g_assert (method->klass->generic_class);
gklass = method->klass->generic_class->container_class;
//g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
for (i = 0; i < generic_array_method_num; i++) {
+ MonoError error;
MonoMethod *m = generic_array_method_info [i].array_method;
MonoMethod *inflated;
- inflated = mono_class_inflate_generic_method (m, &tmp_context);
+ inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
}
}
}
}
- /* CAS - SecurityAction.InheritanceDemand */
- if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_class (class, class->parent);
- }
-
mono_stats.initialized_class_count++;
if (class->generic_class && !class->generic_class->is_dynamic) {
if (!class->enumtype) {
if (!mono_metadata_interfaces_from_typedef_full (
- image, type_token, &interfaces, &icount, FALSE, context)){
- mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
+ image, type_token, &interfaces, &icount, FALSE, context, error)){
+
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
return NULL;
mono_generic_class_setup_parent (klass, gklass);
if (gclass->is_dynamic) {
- klass->inited = 1;
+ /*
+ * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
+ * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
+ * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
+ */
+ if (!gklass->wastypebuilder)
+ klass->inited = 1;
mono_class_setup_supertypes (klass);
/*Init these fields to sane values*/
klass->min_align = 1;
- klass->instance_size = sizeof (gpointer);
+ /*
+ * This makes sure the the value size of this class is equal to the size of the types the gparam is
+ * constrained to, the JIT depends on this.
+ */
+ klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
mono_memory_barrier ();
klass->size_inited = 1;
+ klass->setup_fields_called = 1;
mono_class_setup_supertypes (klass);
static MonoClass *
get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
{
- int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
+ int n = mono_generic_param_num (param);
MonoImage *image = param->image;
+ MonoClass *klass = NULL;
GHashTable *ht;
g_assert (image);
+ if (param->gshared_constraint) {
+ ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
+ if (ht) {
+ if (take_lock)
+ mono_image_lock (image);
+ klass = g_hash_table_lookup (ht, param);
+ if (take_lock)
+ mono_image_unlock (image);
+ }
+ return klass;
+ }
+
if (n < FAST_CACHE_SIZE) {
if (is_mvar)
return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
else
return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
} else {
- MonoClass *klass = NULL;
ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
if (ht) {
if (take_lock)
static void
set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
{
- int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
+ int n = mono_generic_param_num (param);
MonoImage *image = param->image;
g_assert (image);
- if (n < FAST_CACHE_SIZE) {
+ if (param->gshared_constraint) {
+ GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
+ if (!ht) {
+ ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
+ mono_memory_barrier ();
+ if (is_mvar)
+ image->mvar_cache_constrained = ht;
+ else
+ image->var_cache_constrained = ht;
+ }
+ g_hash_table_insert (ht, param, klass);
+ } else if (n < FAST_CACHE_SIZE) {
if (is_mvar) {
/* Requires locking to avoid droping an already published class */
if (!image->mvar_cache_fast)
#endif
class->cast_class = mono_defaults.int64_class;
break;
+ default:
+ break;
}
class->element_class = eclass;
if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
class = mono_class_inflate_generic_class_checked (class, context, &error);
- if (!class) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error); /*FIXME don't swallow this error */
- }
+ g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
return class;
}
return NULL;
}
-/**
- * mono_class_from_name:
- * @image: The MonoImage where the type is looked up in
- * @name_space: the type namespace
- * @name: the type short name.
- *
- * Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.
- *
- * To reference nested classes, use the "/" character as a separator.
- * For example use "Foo/Bar" to reference the class Bar that is nested
- * inside Foo, like this: "class Foo { class Bar {} }".
- */
MonoClass *
-mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
+mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
{
GHashTable *nspace_table;
MonoImage *loaded_image;
char *nested;
char buf [1024];
+ mono_error_init (error);
+
if ((nested = strchr (name, '/'))) {
int pos = nested - name;
int len = strlen (name);
token = MONO_TOKEN_TYPE_DEF | token;
- class = mono_class_get (image, token);
+ class = mono_class_get_checked (image, token, error);
if (nested)
return return_nested_in (class, nested);
return class;
}
+/**
+ * mono_class_from_name:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * Obtains a MonoClass with a given namespace and a given name which
+ * is located in the given MonoImage.
+ *
+ * To reference nested classes, use the "/" character as a separator.
+ * For example use "Foo/Bar" to reference the class Bar that is nested
+ * inside Foo, like this: "class Foo { class Bar {} }".
+ */
+MonoClass *
+mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+ MonoError error;
+ MonoClass *klass;
+
+ klass = mono_class_from_name_checked (image, name_space, name, &error);
+ if (!mono_error_ok (&error)) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+ }
+ return klass;
+}
+
/**
* mono_class_is_subclass_of:
* @klass: class to probe if it is a subclass of another one
if (!klass->has_cctor)
return NULL;
- if (mono_class_get_cached_class_info (klass, &cached_info))
- return mono_get_method (klass->image, cached_info.cctor_token, klass);
+ if (mono_class_get_cached_class_info (klass, &cached_info)) {
+ MonoError error;
+ MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
+ if (!mono_error_ok (&error))
+ g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
+ return result;
+ }
if (klass->generic_class && !klass->methods)
return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
if (!mono_class_has_finalizer (klass))
return NULL;
- if (mono_class_get_cached_class_info (klass, &cached_info))
- return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
- else {
+ if (mono_class_get_cached_class_info (klass, &cached_info)) {
+ MonoError error;
+ MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
+ if (!mono_error_ok (&error))
+ g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
+ return result;
+ }else {
mono_class_setup_vtable (klass);
return klass->vtable [finalize_slot];
}
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
return sizeof (gpointer);
case MONO_TYPE_I8:
case MONO_TYPE_U8:
case MONO_TYPE_GENERICINST:
type = &type->data.generic_class->container_class->byval_arg;
goto handle_enum;
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR: {
+ int align;
+ return mono_type_size (type, &align);
+ }
case MONO_TYPE_VOID:
return 0;
mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
MonoGenericContext *context)
{
+ MonoError error;
+ gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
+ g_assert (mono_error_ok (&error));
+ return res;
+}
+
+gpointer
+mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
+ MonoGenericContext *context, MonoError *error)
+{
+ mono_error_init (error);
+
if (image_is_dynamic (image)) {
MonoClass *tmp_handle_class;
gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
case MONO_TOKEN_TYPE_DEF:
case MONO_TOKEN_TYPE_REF:
case MONO_TOKEN_TYPE_SPEC: {
- MonoError error;
MonoType *type;
if (handle_class)
*handle_class = mono_defaults.typehandle_class;
- type = mono_type_get_checked (image, token, context, &error);
- if (!type) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+ type = mono_type_get_checked (image, token, context, error);
+ if (!type)
return NULL;
- }
+
mono_class_init (mono_class_from_mono_type (type));
/* We return a MonoType* as handle */
return type;
}
case MONO_TOKEN_FIELD_DEF: {
MonoClass *class;
- MonoError error;
guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
- if (!type)
+ if (!type) {
+ mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
return NULL;
+ }
if (handle_class)
*handle_class = mono_defaults.fieldhandle_class;
- class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
- if (!class) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+ class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
+ if (!class)
return NULL;
- }
+
mono_class_init (class);
return mono_class_get_field (class, token);
}
case MONO_TOKEN_METHOD_DEF:
case MONO_TOKEN_METHOD_SPEC: {
MonoMethod *meth;
- meth = mono_get_method_full (image, token, NULL, context);
+ meth = mono_get_method_checked (image, token, NULL, context, error);
if (handle_class)
*handle_class = mono_defaults.methodhandle_class;
+ if (!meth)
+ return NULL;
+
return meth;
}
case MONO_TOKEN_MEMBER_REF: {
sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
mono_metadata_decode_blob_size (sig, &sig);
if (*sig == 0x6) { /* it's a field */
- MonoError error;
MonoClass *klass;
MonoClassField *field;
- field = mono_field_from_token_checked (image, token, &klass, context, &error);
+ field = mono_field_from_token_checked (image, token, &klass, context, error);
if (handle_class)
*handle_class = mono_defaults.fieldhandle_class;
- if (!field) {
- mono_loader_set_error_from_mono_error (&error);
- mono_error_cleanup (&error); /* FIXME Don't swallow the error */
- }
return field;
} else {
MonoMethod *meth;
- meth = mono_get_method_full (image, token, NULL, context);
+ meth = mono_get_method_checked (image, token, NULL, context, error);
if (handle_class)
*handle_class = mono_defaults.methodhandle_class;
return meth;
}
}
default:
- g_warning ("Unknown token 0x%08x in ldtoken", token);
- break;
+ mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
}
return NULL;
}
}
if (i < klass->method.count) {
- res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
+ MonoError error;
+ res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+
/* Add 1 here so the if (*iter) check fails */
*iter = GUINT_TO_POINTER (i + 1);
return res;
/* Search directly in the metadata to avoid calling setup_methods () */
for (i = 0; i < klass->method.count; ++i) {
+ MonoError error;
guint32 cols [MONO_METHOD_SIZE];
MonoMethod *method;
MonoMethodSignature *sig;
mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
- method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
+ method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
+ if (!method) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ continue;
+ }
if (param_count == -1) {
res = method;
break;
}
- sig = mono_method_signature (method);
- if (sig && sig->param_count == param_count) {
+ sig = mono_method_signature_checked (method, &error);
+ if (!sig) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ continue;
+ }
+ if (sig->param_count == param_count) {
res = method;
break;
}
if (klass->generic_class && !klass->methods) {
res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
- if (res)
- res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
+ if (res) {
+ MonoError error;
+ res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ }
return res;
}
gpointer exception_data = mono_class_get_exception_data (klass);
switch (klass->exception_type) {
-#ifndef DISABLE_SECURITY
- case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
- MonoDomain *domain = mono_domain_get ();
- MonoSecurityManager* secman = mono_security_manager_get_methods ();
- MonoMethod *method = exception_data;
- guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
- MonoObject *exc = NULL;
- gpointer args [4];
-
- args [0] = &error;
- args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
- args [2] = mono_type_get_object (domain, &klass->byval_arg);
- args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
-
- mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
- return (MonoException*) exc;
- }
-#endif
case MONO_EXCEPTION_TYPE_LOAD: {
MonoString *name;
MonoException *ex;
case MONO_TYPE_GENERICINST:
if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
return FALSE;
+ default:
+ break;
}
}
return TRUE;
case MONO_TYPE_I:
case MONO_TYPE_U:
return TRUE;
+ default:
+ return FALSE;
}
- return FALSE;
}
/**