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 {
*/
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;
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];
};
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;
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);
}
} 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++;
#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;
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;
}
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;
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*
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;
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);
}