X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=0500a054c2feed85cfec5bcdb794549026a6ef2f;hb=00e3f277acc4d5f83ba34b5431313fe77e7ce0f7;hp=cbfe08b9eb280a742c4506ba9f2d982159281804;hpb=a779b309ab59e88b4f29666fab166916ad815622;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index cbfe08b9eb2..0500a054c2f 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -900,7 +900,16 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k method = imethod->declaring; } - if (!method->is_generic && !method->klass->generic_container) + /* + * A method only needs to be inflated if the context has argument for which it is + * parametric. Eg: + * + * class Foo { void Bar(); } - doesn't need to be inflated if only mvars' are supplied + * class Foo { void Bar (); } - doesn't need to be if only vars' are supplied + * + */ + if (!((method->is_generic && context->method_inst) || + (method->klass->generic_container && context->class_inst))) return method; /* @@ -3739,12 +3748,11 @@ print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_no } for (i = 0; i < size; ++i) { MonoMethod *cm = vtable [i]; - if (cm) { - char *cm_name = mono_method_full_name (cm, TRUE); - char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N'); - printf (" [%c][%03d][INDEX %03d] %s\n", newness, i, cm->slot, cm_name); - g_free (cm_name); - } + char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil"); + char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N'); + + printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm); + g_free (cm_name); } g_free (full_name); @@ -4146,6 +4154,8 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o if (im->flags & METHOD_ATTRIBUTE_STATIC) continue; + TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1))); + // If there is an explicit implementation, just use it right away, // otherwise look for a matching method if (override_im == NULL) { @@ -4282,6 +4292,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o g_assert (cm->slot < max_vtsize); if (!override_map) override_map = g_hash_table_new (mono_aligned_addr_hash, NULL); + TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n", + mono_method_full_name (m1, 1), m1, + mono_method_full_name (cm, 1), cm)); g_hash_table_insert (override_map, m1, cm); break; } @@ -4316,6 +4329,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o overrides [i * 2 + 1]->slot = decl->slot; if (!override_map) override_map = g_hash_table_new (mono_aligned_addr_hash, NULL); + TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", + mono_method_full_name (decl, 1), decl, + mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1])); g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]); if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) @@ -4328,9 +4344,13 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o * overriden, then change the other occurances too. */ if (override_map) { + MonoMethod *cm; + for (i = 0; i < max_vtsize; ++i) if (vtable [i]) { - MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]); + TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i])); + + cm = g_hash_table_lookup (override_map, vtable [i]); if (cm) vtable [i] = cm; } @@ -6463,10 +6483,10 @@ mono_class_get_field_token (MonoClassField *field) int i; mono_class_setup_fields_locking (klass); - if (klass->exception_type) - return 0; while (klass) { + if (!klass->fields) + return 0; for (i = 0; i < klass->field.count; ++i) { if (&klass->fields [i] == field) { int idx = klass->field.first + i + 1; @@ -6520,7 +6540,9 @@ mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_typ if (!klass->ext->field_def_values [field_index].data) { cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0); - g_assert (cindex); + if (!cindex) + return NULL; + g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)); mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE); @@ -7297,11 +7319,15 @@ mono_class_has_variant_generic_params (MonoClass *klass) static gboolean mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv) { + if (target == candidate) + return TRUE; + if (check_for_reference_conv && mono_type_is_generic_argument (&target->byval_arg) && mono_type_is_generic_argument (&candidate->byval_arg)) { MonoGenericParam *gparam = candidate->byval_arg.data.generic_param; MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam); + if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0) return FALSE; } @@ -7326,6 +7352,9 @@ mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass); MonoGenericContainer *container = klass_gtd->generic_container; + if (klass == oklass) + return TRUE; + /*Viable candidates are instances of the same generic interface*/ if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd) return FALSE; @@ -7337,7 +7366,7 @@ mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]); MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]); - if (param1_class->valuetype != param2_class->valuetype) + if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class)) return FALSE; /*