X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fobject.c;h=a7f45a0a635b177922699ee6fb9432cb2cd5abde;hb=dc494c191c1e150102e848a2aea7a6a403afc90c;hp=aeef675dbf4eff38c03991e8addf23d8ee1ceb4e;hpb=d09d585f3e74fb209b74e397659aaf7ba83ce41e;p=mono.git diff --git a/mono/metadata/object.c b/mono/metadata/object.c index aeef675dbf4..a7f45a0a635 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -11,14 +11,22 @@ #include #include #include +#include #include +#include #include #include +#include #include #if HAVE_BOEHM_GC #include #endif +MonoStats mono_stats; + +/* next object id for object hashcode */ +static guint32 uoid = 0; + void mono_runtime_object_init (MonoObject *this) { @@ -59,7 +67,234 @@ mono_runtime_class_init (MonoClass *klass) } } /* No class constructor found */ +} + +static gpointer +default_trampoline (MonoMethod *method) +{ + return method; +} + +static gpointer +default_remoting_trampoline (MonoMethod *method) +{ + g_error ("remoting not installed"); + return NULL; +} + +static MonoTrampoline arch_create_jit_trampoline = default_trampoline; +static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline; + +void +mono_install_trampoline (MonoTrampoline func) +{ + arch_create_jit_trampoline = func? func: default_trampoline; +} + +void +mono_install_remoting_trampoline (MonoTrampoline func) +{ + arch_create_remoting_trampoline = func? func: default_remoting_trampoline; +} + +#if 0 && HAVE_BOEHM_GC +static void +vtable_finalizer (void *obj, void *data) { + g_print ("%s finalized (%p)\n", (char*)data, obj); +} +#endif + +/** + * mono_class_vtable: + * @domain: the application domain + * @class: the class to initialize + * + * VTables are domain specific because we create domain specific code, and + * they contain the domain specific static class data. + */ +MonoVTable * +mono_class_vtable (MonoDomain *domain, MonoClass *class) +{ + MonoClass *k; + MonoVTable *vt; + MonoClassField *field; + guint32 cindex; + guint32 cols [MONO_CONSTANT_SIZE]; + const char *p; + char *t; + int i, len; + + g_assert (class); + + /* can interfaces have static fields? */ + if (class->flags & TYPE_ATTRIBUTE_INTERFACE) + g_assert_not_reached (); + + mono_domain_lock (domain); + if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) { + mono_domain_unlock (domain); + return vt; + } + + if (!class->inited) + mono_class_init (class); + +// mono_stats.used_class_count++; +// mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer); + + vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) + + class->vtable_size * sizeof (gpointer)); + vt->klass = class; + vt->domain = domain; + + if (class->class_size) { +#if HAVE_BOEHM_GC + vt->data = GC_malloc (class->class_size + 8); + /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/ + /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/ + mono_g_hash_table_insert (domain->static_data_hash, class, vt->data); +#else + vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8); + +#endif +// mono_stats.class_static_data_size += class->class_size + 8; + } + + for (i = class->field.first; i < class->field.last; ++i) { + field = &class->fields [i - class->field.first]; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + continue; + if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) + continue; + cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1)); + if (!cindex) { + g_warning ("constant for field %s not found", field->name); + continue; + } + mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE); + p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]); + len = mono_metadata_decode_blob_size (p, &p); + t = (char*)vt->data + field->offset; + /* should we check that the type matches? */ + switch (cols [MONO_CONSTANT_TYPE]) { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_U1: + case MONO_TYPE_I1: + *t = *p; + break; + case MONO_TYPE_CHAR: + case MONO_TYPE_U2: + case MONO_TYPE_I2: { + guint16 *val = (guint16*)t; + *val = read16 (p); + break; + } + case MONO_TYPE_U4: + case MONO_TYPE_I4: { + guint32 *val = (guint32*)t; + *val = read32 (p); + break; + } + case MONO_TYPE_U8: + case MONO_TYPE_I8: { + guint64 *val = (guint64*)t; + *val = read64 (p); + break; + } + case MONO_TYPE_R4: { + float *val = (float*)t; + readr4 (p, val); + break; + } + case MONO_TYPE_R8: { + double *val = (double*)t; + readr8 (p, val); + break; + } + case MONO_TYPE_STRING: { + //gpointer *val = (gpointer*)t; + //*val = mono_string_new_utf16 (domain, (const guint16*)p, len/2); + break; + } + case MONO_TYPE_CLASS: + /* nothing to do, we malloc0 the data and the value can be 0 only */ + break; + default: + g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]); + } + } + vt->max_interface_id = class->max_interface_id; + + vt->interface_offsets = mono_mempool_alloc0 (domain->mp, + sizeof (gpointer) * (class->max_interface_id + 1)); + + /* initialize interface offsets */ + for (k = class; k ; k = k->parent) { + for (i = 0; i < k->interface_count; i++) { + int slot; + MonoClass *ic = k->interfaces [i]; + slot = class->interface_offsets [ic->interface_id]; + vt->interface_offsets [ic->interface_id] = &vt->vtable [slot]; + } + } + + /* initialize vtable */ + for (i = 0; i < class->vtable_size; ++i) { + MonoMethod *cm; + + if ((cm = class->vtable [i])) + vt->vtable [i] = arch_create_jit_trampoline (cm); + } + + mono_g_hash_table_insert (domain->class_vtable_hash, class, vt); + mono_domain_unlock (domain); + + mono_runtime_class_init (class); + + return vt; +} + +/** + * mono_class_proxy_vtable: + * @domain: the application domain + * @class: the class to proxy + * + * Creates a vtable for transparent proxies. It is basically + * a copy of the real vtable of @class, but all function pointers invoke + * the remoting functions, and vtable->klass points to the + * transparent proxy class, and not to @class. + */ +MonoVTable * +mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class) +{ + MonoVTable *vt, *pvt; + int i, vtsize; + + if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class))) + return pvt; + + vt = mono_class_vtable (domain, class); + vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer); + +// mono_stats.class_vtable_size += vtsize; + + pvt = mono_mempool_alloc (domain->mp, vtsize); + memcpy (pvt, vt, vtsize); + + pvt->klass = mono_defaults.transparent_proxy_class; + + /* initialize vtable */ + for (i = 0; i < class->vtable_size; ++i) { + MonoMethod *cm; + + if ((cm = class->vtable [i])) + pvt->vtable [i] = arch_create_remoting_trampoline (cm); + } + + mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt); + + return pvt; } static MonoInvokeFunc default_mono_runtime_invoke = NULL; @@ -101,39 +336,40 @@ MonoObject* mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params) { MonoMethodSignature *sig = method->signature; - gpointer *pa; + gpointer *pa = NULL; int i; + + if (NULL != params) { + pa = alloca (sizeof (gpointer) * mono_array_length (params)); + for (i = 0; i < mono_array_length (params); i++) { + if (sig->params [i]->byref) { + /* nothing to do */ + } - pa = alloca (sizeof (gpointer) * params->bounds->length); - - for (i = 0; i < params->bounds->length; i++) { - if (sig->params [i]->byref) { - /* nothing to do */ - } - - switch (sig->params [i]->type) { - case MONO_TYPE_U1: - case MONO_TYPE_I1: - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_U2: - case MONO_TYPE_I2: - case MONO_TYPE_CHAR: - case MONO_TYPE_U: - case MONO_TYPE_I: - case MONO_TYPE_U4: - case MONO_TYPE_I4: - case MONO_TYPE_U8: - case MONO_TYPE_I8: - case MONO_TYPE_VALUETYPE: - pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject); - break; - case MONO_TYPE_STRING: - case MONO_TYPE_OBJECT: - case MONO_TYPE_CLASS: - pa [i] = (char *)(((gpointer *)params->vector)[i]); - break; - default: - g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type); + switch (sig->params [i]->type) { + case MONO_TYPE_U1: + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_U2: + case MONO_TYPE_I2: + case MONO_TYPE_CHAR: + case MONO_TYPE_U: + case MONO_TYPE_I: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_VALUETYPE: + pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject); + break; + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: + case MONO_TYPE_CLASS: + pa [i] = (char *)(((gpointer *)params->vector)[i]); + break; + default: + g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type); + } } } @@ -158,7 +394,8 @@ void * mono_object_allocate (size_t size) { #if HAVE_BOEHM_GC - void *o = GC_debug_malloc (size, "object", 1); + /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */ + void *o = GC_malloc (size); #else void *o = calloc (1, size); #endif @@ -195,24 +432,38 @@ mono_object_free (MonoObject *o) MonoObject * mono_object_new (MonoDomain *domain, MonoClass *klass) { - static guint32 uoid = 0; - MonoObject *o; + return mono_object_new_specific (mono_class_vtable (domain, klass)); +} - if (!klass->inited) - mono_class_init (klass); +/** + * mono_object_new_specific: + * @vtable: the vtable of the object that we want to create + * + * Returns: A newly created object with class and domain specified + * by @vtable + */ +MonoObject * +mono_object_new_specific (MonoVTable *vtable) +{ + MonoObject *o; + mono_stats.new_object_count++; /* thread safe? */ - if (klass->ghcimpl) { - o = mono_object_allocate (klass->instance_size); - o->vtable = mono_class_vtable (domain, klass); - } else { + /* if the returned pointer is not the same as the address returned by GC_malloc(), + * we need to change also metadata/gc.c to take into account the new offset. + */ + if (vtable->klass->ghcimpl) + o = mono_object_allocate (vtable->klass->instance_size); + else { guint32 *t; - t = mono_object_allocate (klass->instance_size + 4); + t = mono_object_allocate (vtable->klass->instance_size + 4); *t = ++uoid; o = (MonoObject *)(++t); - o->vtable = mono_class_vtable (domain, klass); } - + o->vtable = vtable; + if (vtable->klass->has_finalize) + mono_object_register_finalizer (o); + return o; } @@ -252,6 +503,8 @@ mono_object_clone (MonoObject *obj) memcpy (o, obj, size); + if (obj->vtable->klass->has_finalize) + mono_object_register_finalizer (o); return o; } @@ -268,6 +521,17 @@ mono_array_clone (MonoArray *array) int size, i; guint32 *sizes; MonoClass *klass = array->obj.vtable->klass; + + if (array->bounds == NULL) { + size = mono_array_length (array); + o = mono_array_new_full (((MonoObject *)array)->vtable->domain, + klass, &size, NULL); + + size *= mono_array_element_size (klass); + memcpy (o, array, sizeof (MonoArray) + size); + + return o; + } sizes = alloca (klass->rank * sizeof(guint32) * 2); size = mono_array_element_size (klass); @@ -297,7 +561,7 @@ MonoArray* mono_array_new_full (MonoDomain *domain, MonoClass *array_class, guint32 *lengths, guint32 *lower_bounds) { - guint32 byte_len; + guint32 byte_len, len; MonoObject *o; MonoArray *array; MonoArrayBounds *bounds; @@ -307,20 +571,29 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_class_init (array_class); byte_len = mono_array_element_size (array_class); + len = 1; -#if HAVE_BOEHM_GC - bounds = GC_debug_malloc (sizeof (MonoArrayBounds) * array_class->rank, "bounds", 0); -#else - bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank); -#endif - for (i = 0; i < array_class->rank; ++i) { - bounds [i].length = lengths [i]; - byte_len *= lengths [i]; + if (array_class->rank == 1 && + (lower_bounds == NULL || lower_bounds [0] == 0)) { + bounds = NULL; + len = lengths [0]; + } else { + #if HAVE_BOEHM_GC + bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank); + #else + bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank); + #endif + for (i = 0; i < array_class->rank; ++i) { + bounds [i].length = lengths [i]; + len *= lengths [i]; + } + + if (lower_bounds) + for (i = 0; i < array_class->rank; ++i) + bounds [i].lower_bound = lower_bounds [i]; } - if (lower_bounds) - for (i = 0; i < array_class->rank; ++i) - bounds [i].lower_bound = lower_bounds [i]; + byte_len *= len; /* * Following three lines almost taken from mono_object_new (): * they need to be kept in sync. @@ -333,7 +606,7 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, array = (MonoArray*)o; array->bounds = bounds; - array->max_length = bounds [0].length; + array->max_length = len; return array; } @@ -354,7 +627,35 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n) ac = mono_array_class_get (&eclass->byval_arg, 1); g_assert (ac != NULL); - return mono_array_new_full (domain, ac, &n, NULL); + return mono_array_new_specific (mono_class_vtable (domain, ac), n); +} + +/* + * mono_array_new_specific: + * @vtable: a vtable in the appropriate domain for an initialized class + * @n: number of array elements + * + * This routine is a fast alternative to mono_array_new() for code which + * can be sure about the domain it operates in. + */ +MonoArray * +mono_array_new_specific (MonoVTable *vtable, guint32 n) +{ + MonoObject *o; + MonoArray *ao; + gsize byte_len; + + byte_len = n * mono_array_element_size (vtable->klass); + o = mono_object_allocate (sizeof (MonoArray) + byte_len); + if (!o) + G_BREAKPOINT (); + o->vtable = vtable; + + ao = (MonoArray *)o; + ao->bounds = NULL; + ao->max_length = n; + + return ao; } /** @@ -368,18 +669,43 @@ MonoString * mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len) { MonoString *s; - MonoArray *ca; - - s = (MonoString*)mono_object_new (domain, mono_defaults.string_class); + + s = mono_string_new_size (domain, len); g_assert (s != NULL); - ca = (MonoArray *)mono_array_new (domain, mono_defaults.char_class, len); - g_assert (ca != NULL); - - s->c_str = ca; - s->length = len; + memcpy (mono_string_chars (s), text, len * 2); - memcpy (ca->vector, text, len * 2); + return s; +} + +/** + * mono_string_new_size: + * @text: a pointer to an utf16 string + * @len: the length of the string + * + * Returns: A newly created string object of @len + */ +MonoString * +mono_string_new_size (MonoDomain *domain, gint32 len) +{ + MonoString *s; + + /* + * enable to get a good speedup: we still need to figure out + * how the sync structure is freed. + */ +#ifdef 0 && HAVE_BOEHM_GC + s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2)); + s->object.synchronisation = 0; + mono_string_chars (s) [len] = 0; +#else + s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2)); +#endif + if (!s) + G_BREAKPOINT (); + + s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class); + s->length = len; return s; } @@ -478,6 +804,8 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value) memcpy ((char *)res + sizeof (MonoObject), value, size); + if (class->has_finalize) + mono_object_register_finalizer (res); return res; } @@ -510,15 +838,14 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass) } else { if (oklass == mono_defaults.transparent_proxy_class) { /* fixme: add check for IRemotingTypeInfo */ - MonoRealProxy *rp = ((MonoTransparentProxy *)obj)->rp; - MonoType *type; - type = ((MonoReflectionType *)rp->class_to_proxy)->type; - oklass = mono_class_from_mono_type (type); + oklass = ((MonoTransparentProxy *)obj)->klass; } - if (oklass->rank && oklass->rank == klass->rank) { - if ((oklass->element_class->baseval - klass->element_class->baseval) <= + if (klass->rank) { + if (oklass->rank == klass->rank && + (oklass->element_class->baseval - klass->element_class->baseval) <= klass->element_class->diffval) return obj; + } else if ((oklass->baseval - klass->baseval) <= klass->diffval) return obj; } @@ -531,6 +858,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert) { MonoGHashTable *ldstr_table; MonoString *res; + MonoDomain *domain; char *ins = g_malloc (4 + str->length * 2); char *p; int bloblen; @@ -550,7 +878,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert) #if G_BYTE_ORDER != G_LITTLE_ENDIAN { int i; - char *p2 = mono_array_addr (str->c_str, char, 0); + char *p2 = mono_string_chars (str); for (i = 0; i < str->length; ++i) { *p++ = p2 [1]; *p++ = p2 [0]; @@ -558,17 +886,22 @@ mono_string_is_interned_lookup (MonoString *str, int insert) } } #else - memcpy (p, str->c_str->vector, str->length * 2); + memcpy (p, mono_string_chars (str), str->length * 2); #endif - ldstr_table = ((MonoObject *)str)->vtable->domain->ldstr_table; + domain = ((MonoObject *)str)->vtable->domain; + ldstr_table = domain->ldstr_table; + mono_domain_lock (domain); if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) { + mono_domain_unlock (domain); g_free (ins); return res; } if (insert) { mono_g_hash_table_insert (ldstr_table, ins, str); + mono_domain_unlock (domain); return str; } + mono_domain_unlock (domain); g_free (ins); return NULL; } @@ -601,9 +934,12 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx) size_t len2; sig = str = mono_metadata_user_string (image, idx); - - if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) + + mono_domain_lock (domain); + if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) { + mono_domain_unlock (domain); return o; + } len2 = mono_metadata_decode_blob_size (str, &str); len2 >>= 1; @@ -620,6 +956,7 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx) } #endif mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o); + mono_domain_unlock (domain); return o; } @@ -634,19 +971,15 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx) char * mono_string_to_utf8 (MonoString *s) { - char *as, *vector; + char *as; GError *error = NULL; g_assert (s != NULL); - if (!s->length || !s->c_str) + if (!s->length) return g_strdup (""); - vector = (char*)s->c_str->vector; - - g_assert (vector != NULL); - - as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error); + as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error); if (error) g_warning (error->message); @@ -673,7 +1006,7 @@ mono_string_to_utf16 (MonoString *s) as [(s->length * 2)] = '\0'; as [(s->length * 2) + 1] = '\0'; - if (!s->length || !s->c_str) { + if (!s->length) { return (gunichar2 *)(as); } @@ -846,7 +1179,6 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, MonoDomain *domain = mono_domain_get (); MonoMethod *method = msg->method->method; MonoMethodSignature *sig = method->signature; - MonoObject *res; int i, j, outarg_count = 0; for (i = 0; i < sig->param_count; i++) {