Remove the data field from MonoVTable to reduce memory usage.
authorPaolo Molaro <lupus@oddwiz.org>
Fri, 10 Jun 2011 13:08:33 +0000 (15:08 +0200)
committerPaolo Molaro <lupus@oddwiz.org>
Mon, 27 Jun 2011 14:04:32 +0000 (16:04 +0200)
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.

mono/metadata/appdomain.c
mono/metadata/class-internals.h
mono/metadata/debug-helpers.c
mono/metadata/mono-debug-debugger.h
mono/metadata/object-internals.h
mono/metadata/object.c
mono/mini/jit-icalls.c
mono/mini/method-to-ir.c
mono/mini/mini-generic-sharing.c
mono/mini/mini.c

index 56ac6e8bed09736cbad5acc4e97e6b1442dd39f5..f9cb246a676807b76f62da4f0d147a42a6f1c98e 100644 (file)
@@ -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 {
index 1c97b6699223d5e293d2715d9e6f04e519b8d679..698aa28554628c5734d3a487b41cc6cc7753b0a4 100644 (file)
@@ -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];       
 };
 
index 1cf21e31b702c20ca165a913ad217e7c8ce2a745..afeb91bbf13cf226d040aada2ffbaf981ca5cd32 100644 (file)
@@ -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) {
index ed6efa072945478e099bcf7ad2a70db1f80a9f8d..450302a443d109c9f8d28c6757554937b275c30b 100644 (file)
@@ -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);
 
index 8ec7d6c4d44ce2aba352fb9132add5b64f00ba6e..bb3d8503e8984f5ebb1cd7d0cd7d546196b99c79 100644 (file)
@@ -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;
 
index 91c8dd289d7133e002353651e10a84a709e0c3ed..86cc1ce29997fbe92ac6501c378a70b7566f6978 100644 (file)
@@ -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);
 }
index 578cc35c1026841f43c1dda666ebf2e3bc2b230b..17d39b1c21fc27503b2987453e99086c13afa98f 100644 (file)
@@ -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;
 }
index b11a4cc4a305c3f455f0537aa4247463796181f3..ebf6dabbf1ae6745e56c6aacb5ba36d55c71cf67 100644 (file)
@@ -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;
index 8706fa3c31adaf4ce1c469cc0927a6ff94bebc72..63f70e5d7328138a529da7512031a84c5b1e6cc5 100644 (file)
@@ -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;
index 43bc157c3885f7aebfcbf66e263bceb1c2ac328e..0b589cafcd60363693fb1715f412d19f05eac8ff 100644 (file)
@@ -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: {