From b0cff959e47c3d9955e6675364bf71404cd74bac Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Thu, 2 Oct 2014 21:04:13 -0700 Subject: [PATCH] [runtime] Fix allocation size calculation for strings in 64-bit builds. Depending on alignment and packing, part of the string might be inside the MonoString struct boundaries. This e.g. shows up on 64-bit builds of mono where we were allocating 4 extra bytes per string. --- mono/metadata/boehm-gc.c | 2 +- mono/metadata/object.c | 4 ++-- mono/metadata/sgen-alloc.c | 10 +++++----- mono/metadata/sgen-gc.h | 4 ++-- mono/metadata/string-icalls.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 3320820f877..a3f8296459a 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -753,7 +753,7 @@ create_allocator (int atype, int tls_key) bytes_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); if (atype == ATYPE_STRING) { /* a string alloator method takes the args: (vtable, len) */ - /* bytes = (sizeof (MonoString) + ((len + 1) * 2)); */ + /* bytes = (offsetof (MonoString, chars) + ((len + 1) * 2)); */ mono_mb_emit_ldarg (mb, 1); mono_mb_emit_icon (mb, 1); mono_mb_emit_byte (mb, MONO_CEE_ADD); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index a2aa759293b..b9abf073f05 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -5041,10 +5041,10 @@ mono_string_new_size (MonoDomain *domain, gint32 len) size_t size; /* check for overflow */ - if (len < 0 || len > ((SIZE_MAX - sizeof (MonoString) - 2) / 2)) + if (len < 0 || len > ((SIZE_MAX - offsetof (MonoString, chars) - 2) / 2)) mono_gc_out_of_memory (-1); - size = (sizeof (MonoString) + ((len + 1) * 2)); + size = (offsetof (MonoString, chars) + ((len + 1) * 2)); g_assert (size > 0); vtable = mono_class_vtable (domain, mono_defaults.string_class); diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index d9a52e9b195..5d343adbe18 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -887,7 +887,7 @@ create_allocator (int atype) /* * a string allocator method takes the args: (vtable, len) * - * bytes = sizeof (MonoString) + ((len + 1) * 2) + * bytes = offsetof (MonoString, chars) + ((len + 1) * 2) * * condition: * @@ -895,11 +895,11 @@ create_allocator (int atype) * * therefore: * - * sizeof (MonoString) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1 + * offsetof (MonoString, chars) + ((len + 1) * 2) <= INT32_MAX - (SGEN_ALLOC_ALIGN - 1) + * len <= (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - offsetof (MonoString, chars)) / 2 - 1 */ mono_mb_emit_ldarg (mb, 1); - mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - sizeof (MonoString)) / 2 - 1); + mono_mb_emit_icon (mb, (INT32_MAX - (SGEN_ALLOC_ALIGN - 1) - MONO_STRUCT_OFFSET (MonoString, chars)) / 2 - 1); pos = mono_mb_emit_short_branch (mb, MONO_CEE_BLE_UN_S); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); @@ -911,7 +911,7 @@ create_allocator (int atype) mono_mb_emit_icon (mb, 1); mono_mb_emit_byte (mb, MONO_CEE_SHL); //WE manually fold the above + 2 here - mono_mb_emit_icon (mb, sizeof (MonoString) + 2); + mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoString, chars) + 2); mono_mb_emit_byte (mb, CEE_ADD); mono_mb_emit_stloc (mb, size_var); } else { diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 076d03bc9d7..9f21b3e76f0 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -731,7 +731,7 @@ slow_object_get_size (MonoVTable *vtable, MonoObject* o) * mono_array_length_fast not using the object's vtable. */ if (klass == mono_defaults.string_class) { - return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; } else if (klass->rank) { MonoArray *array = (MonoArray*)o; size_t size = sizeof (MonoArray) + klass->sizes.element_size * mono_array_length_fast (array); @@ -782,7 +782,7 @@ sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o) if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_BITMAP) { mword size = descr & 0xfff8; if (size == 0) /* This is used to encode a string */ - return sizeof (MonoString) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; return size; } else if (type == DESC_TYPE_VECTOR) { int element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE; diff --git a/mono/metadata/string-icalls.c b/mono/metadata/string-icalls.c index 0927141e792..388d866141f 100644 --- a/mono/metadata/string-icalls.c +++ b/mono/metadata/string-icalls.c @@ -65,5 +65,5 @@ ves_icall_System_String_GetLOSLimit (void) { int limit = mono_gc_get_los_limit (); - return (limit - 2 - sizeof (MonoString)) / 2; + return (limit - 2 - offsetof (MonoString, chars)) / 2; } -- 2.11.4.GIT