From 7dbd43e8878c613560ebb7a9cbd9ecb38bd3c37b Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Tue, 17 Jul 2012 13:23:03 -0300 Subject: [PATCH] When calculating allowance, don't blindly cast from double to uint as it might not saturate the result. * sgen-gc.c (try_calculate_minor_collection_allowance): For workloads with very high survival rates the calculated allowance_target can overflow a mword on 32bits systems. Given this behavior is unspecified and we've been bitten by it, let's take the safe side and manually saturate it. --- mono/metadata/sgen-conf.h | 2 ++ mono/metadata/sgen-memory-governor.c | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mono/metadata/sgen-conf.h b/mono/metadata/sgen-conf.h index 89960397fe7..19f28cde038 100644 --- a/mono/metadata/sgen-conf.h +++ b/mono/metadata/sgen-conf.h @@ -29,8 +29,10 @@ #if SIZEOF_VOID_P == 4 typedef guint32 mword; +#define MWORD_MAX_VALUE ((uint32_t) 0xffffffff) #else typedef guint64 mword; +#define MWORD_MAX_VALUE (G_MAXUINT64) #endif diff --git a/mono/metadata/sgen-memory-governor.c b/mono/metadata/sgen-memory-governor.c index 2e7c7690a8d..e2e6c36a8c7 100644 --- a/mono/metadata/sgen-memory-governor.c +++ b/mono/metadata/sgen-memory-governor.c @@ -77,6 +77,14 @@ static mword last_collection_los_memory_alloced; static mword sgen_memgov_available_free_space (void); +static mword +double_to_mword_with_saturation (double value) +{ + if (value >= (double)MWORD_MAX_VALUE) + return MWORD_MAX_VALUE; + return (mword)value; +} + /* GC trigger heuristics. */ static void @@ -122,7 +130,7 @@ sgen_memgov_try_calculate_minor_collection_allowance (gboolean overwrite) * * hence: */ - allowance_target = (mword)((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved)); + allowance_target = double_to_mword_with_saturation ((double)save_target * (double)(minor_collection_sections_alloced * major_collector.section_size + last_collection_los_memory_alloced) / (double)(num_major_sections_saved * major_collector.section_size + los_memory_saved)); minor_collection_allowance = MAX (MIN (allowance_target, num_major_sections * major_collector.section_size + los_memory_usage), MIN_MINOR_COLLECTION_ALLOWANCE); -- 2.25.1