From: Paolo Molaro Date: Fri, 10 Jun 2011 13:08:33 +0000 (+0200) Subject: Remove the data field from MonoVTable to reduce memory usage. X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=0e31cd4e854a175cfb05f3220642075f9e87d7c3;p=mono.git Remove the data field from MonoVTable to reduce memory usage. We now store a pointer to the static fields area of a type at the end of the vtable array only when needed, so we save memory for all the types that have no static fields. All the direct accesses to the field have been changed to use the already existing function accessor. --- diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 56ac6e8bed0..f9cb246a676 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -2169,21 +2169,23 @@ clear_cached_vtable (MonoVTable *vtable) MonoClass *klass = vtable->klass; MonoDomain *domain = vtable->domain; MonoClassRuntimeInfo *runtime_info; + void *data; runtime_info = klass->runtime_info; if (runtime_info && runtime_info->max_domain >= domain->domain_id) runtime_info->domain_vtables [domain->domain_id] = NULL; - if (vtable->data && klass->has_static_refs) - mono_gc_free_fixed (vtable->data); + if (klass->has_static_refs && (data = mono_vtable_get_static_field_data (vtable))) + mono_gc_free_fixed (data); } static G_GNUC_UNUSED void zero_static_data (MonoVTable *vtable) { MonoClass *klass = vtable->klass; + void *data; - if (vtable->data && klass->has_static_refs) - mono_gc_bzero (vtable->data, mono_class_data_size (klass)); + if (klass->has_static_refs && (data = mono_vtable_get_static_field_data (vtable))) + mono_gc_bzero (data, mono_class_data_size (klass)); } typedef struct unload_data { diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index 1c97b669922..698aa285546 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -458,7 +458,6 @@ struct MonoVTable { */ void *gc_descr; MonoDomain *domain; /* each object/vtable belongs to exactly one domain */ - gpointer data; /* to store static class data */ gpointer type; /* System.Type type for klass */ guint8 *interface_bitmap; guint16 max_interface_id; @@ -466,9 +465,12 @@ struct MonoVTable { guint remote : 1; /* class is remotely activated */ guint initialized : 1; /* cctor has been run */ guint init_failed : 1; /* cctor execution failed */ + guint has_static_fields : 1; /* pointer to the data stored at the end of the vtable array */ guint32 imt_collisions_bitmap; MonoRuntimeGenericContext *runtime_generic_context; /* do not add any fields after vtable, the structure is dynamically extended */ + /* vtable contains function pointers to methods or their trampolines, at the + end there may be a slot containing the pointer to the static fields */ gpointer vtable [MONO_ZERO_LEN_ARRAY]; }; diff --git a/mono/metadata/debug-helpers.c b/mono/metadata/debug-helpers.c index 1cf21e31b70..afeb91bbf13 100644 --- a/mono/metadata/debug-helpers.c +++ b/mono/metadata/debug-helpers.c @@ -1003,7 +1003,7 @@ mono_class_describe_statics (MonoClass* klass) if (!vtable) return; - if (!(addr = vtable->data)) + if (!(addr = mono_vtable_get_static_field_data (vtable))) return; for (p = klass; p != NULL; p = p->parent) { diff --git a/mono/metadata/mono-debug-debugger.h b/mono/metadata/mono-debug-debugger.h index ed6efa07294..450302a443d 100644 --- a/mono/metadata/mono-debug-debugger.h +++ b/mono/metadata/mono-debug-debugger.h @@ -57,9 +57,6 @@ void mono_debugger_lock (void); void mono_debugger_unlock (void); void mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg); -void * -mono_vtable_get_static_field_data (MonoVTable *vt); - gchar * mono_debugger_check_runtime_version (const char *filename); diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 8ec7d6c4d44..bb3d8503e89 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -1560,6 +1560,10 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass) MONO_INTERNAL; void mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value) MONO_INTERNAL; +/* exported, used by the debugger */ +void * +mono_vtable_get_static_field_data (MonoVTable *vt); + char * mono_string_to_utf8_ignore (MonoString *s) MONO_INTERNAL; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 91c8dd289d7..86cc1ce2999 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -1834,7 +1834,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean MonoClassRuntimeInfo *runtime_info, *old_info; MonoClassField *field; char *t; - int i; + int i, vtable_slots; int imt_table_bytes = 0; guint32 vtable_size, class_size; guint32 cindex; @@ -1902,8 +1902,14 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean return NULL; } + vtable_slots = class->vtable_size; + /* we add an additional vtable slot to store the pointer to static field data only when needed */ + class_size = mono_class_data_size (class); + if (class_size) + vtable_slots++; + if (ARCH_USE_IMT) { - vtable_size = MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer); + vtable_size = MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer); if (class->interface_offsets_count) { imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE); vtable_size += sizeof (gpointer) * (MONO_IMT_SIZE); @@ -1912,7 +1918,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean } } else { vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) + - MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer); + MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer); } mono_stats.used_class_count++; @@ -1947,7 +1953,8 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean #endif vt->gc_descr = class->gc_descr; - if ((class_size = mono_class_data_size (class))) { + if (class_size) { + /* we store the static field pointer at the end of the vtable: vt->vtable [class->vtable_size] */ if (class->has_static_refs) { gpointer statics_gc_descr; int max_set = 0; @@ -1957,13 +1964,14 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE); /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/ statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1); - vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr); - mono_domain_add_class_static_data (domain, class, vt->data, NULL); + vt->vtable [class->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr); + mono_domain_add_class_static_data (domain, class, vt->vtable [class->vtable_size], NULL); if (bitmap != default_bitmap) g_free (bitmap); } else { - vt->data = mono_domain_alloc0 (domain, class_size); + vt->vtable [class->vtable_size] = mono_domain_alloc0 (domain, class_size); } + vt->has_static_fields = TRUE; mono_stats.class_static_data_size += class_size; } @@ -2015,7 +2023,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean const char *data = mono_field_get_data (field); g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)); - t = (char*)vt->data + field->offset; + t = (char*)mono_vtable_get_static_field_data (vt) + field->offset; /* some fields don't really have rva, they are just zeroed (bss? bug #343083) */ if (!data) continue; @@ -2977,16 +2985,24 @@ mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value) mono_domain_unlock (vt->domain); dest = mono_get_special_static_data (GPOINTER_TO_UINT (addr)); } else { - dest = (char*)vt->data + field->offset; + dest = (char*)mono_vtable_get_static_field_data (vt) + field->offset; } set_value (field->type, dest, value, FALSE); } -/* Used by the debugger */ +/** + * mono_vtable_get_static_field_data: + * + * Internal use function: return a pointer to the memory holding the static fields + * for a class or NULL if there are no static fields. + * This is exported only for use by the debugger. + */ void * mono_vtable_get_static_field_data (MonoVTable *vt) { - return vt->data; + if (!vt->has_static_fields) + return NULL; + return vt->vtable [vt->klass->vtable_size]; } static guint8* @@ -3004,7 +3020,7 @@ mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field) mono_domain_unlock (vt->domain); src = mono_get_special_static_data (GPOINTER_TO_UINT (addr)); } else { - src = (guint8*)vt->data + field->offset; + src = (guint8*)mono_vtable_get_static_field_data (vt) + field->offset; } } else { src = (guint8*)obj + field->offset; @@ -3260,7 +3276,7 @@ mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable * gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field); src = mono_get_special_static_data_for_thread (thread, GPOINTER_TO_UINT (addr)); } else { - src = (char*)vt->data + field->offset; + src = (char*)mono_vtable_get_static_field_data (vt) + field->offset; } set_value (field->type, value, src, TRUE); } diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 578cc35c102..17d39b1c21f 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -784,7 +784,7 @@ mono_class_static_field_address (MonoDomain *domain, MonoClassField *field) if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field))) addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr)); else - addr = (char*)vtable->data + field->offset; + addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset; return addr; } diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index b11a4cc4a30..ebf6dabbf1a 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -8936,7 +8936,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } } - addr = (char*)vtable->data + field->offset; + addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset; if (cfg->compile_aot) EMIT_NEW_SFLDACONST (cfg, ins, field); @@ -8972,7 +8972,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } if (!context_used && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) && vtable->initialized && (ftype->attrs & FIELD_ATTRIBUTE_INIT_ONLY)) { - gpointer addr = (char*)vtable->data + field->offset; + gpointer addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset; int ro_type = ftype->type; if (ro_type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) { ro_type = mono_class_enum_basetype (ftype->data.klass)->type; diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c index 8706fa3c31a..63f70e5d732 100644 --- a/mono/mini/mini-generic-sharing.c +++ b/mono/mini/mini-generic-sharing.c @@ -838,7 +838,7 @@ class_type_info (MonoDomain *domain, MonoClass *class, int info_type) MonoVTable *vtable = mono_class_vtable (domain, class); if (!vtable) mono_raise_exception (mono_class_get_exception_for_failure (class)); - return vtable->data; + return mono_vtable_get_static_field_data (vtable); } case MONO_RGCTX_INFO_KLASS: return class; diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 43bc157c388..0b589cafcd6 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3078,7 +3078,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, if (run_cctors) mono_runtime_class_init (vtable); } - target = (char*)vtable->data + patch_info->data.field->offset; + target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset; break; } case MONO_PATCH_INFO_RVA: {