[wasm] Fix fragmentation caused by large objects allocation (#118099)

This commit is contained in:
Vlad Brezae 2025-07-30 16:53:57 +03:00 committed by GitHub
parent 123627ba0f
commit 02596ba8d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 29 additions and 0 deletions

View File

@ -125,6 +125,12 @@ mword sgen_los_memory_usage = 0;
/* Total memory used by the LOS allocator */
mword sgen_los_memory_usage_total = 0;
#ifdef HOST_WASM
const gboolean sgen_los_enable_sections_allocator = 0;
#else
const gboolean sgen_los_enable_sections_allocator = 1;
#endif
static LOSSection *los_sections = NULL;
static LOSFreeChunks *los_fast_free_lists [LOS_NUM_FAST_SIZES]; /* 0 is for larger sizes */
static mword los_num_objects = 0;
@ -156,6 +162,9 @@ los_consistency_check (void)
int i;
mword memory_usage = 0;
if (!sgen_los_enable_sections_allocator)
return;
FOREACH_LOS_OBJECT_NO_LOCK (obj) {
mword obj_size = sgen_los_object_size (obj);
char *end = obj->data + obj_size;
@ -400,6 +409,11 @@ sgen_los_free_object (LOSObject *obj)
sgen_free_os_memory ((gpointer)SGEN_ALIGN_DOWN_TO ((mword)obj, pagesize), size, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_LOS);
sgen_los_memory_usage_total -= size;
sgen_memgov_release_space (size, SPACE_LOS);
} else if (!sgen_los_enable_sections_allocator) {
size += sizeof (LOSObject);
sgen_free_os_memory (obj, size, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_LOS);
sgen_los_memory_usage_total -= size;
sgen_memgov_release_space (size, SPACE_LOS);
} else {
free_los_section_memory (obj, size + sizeof (LOSObject));
#ifdef LOS_CONSISTENCY_CHECKS
@ -461,6 +475,21 @@ sgen_los_alloc_large_inner (GCVTable vtable, size_t size)
obj = randomize_los_object_start (obj, obj_size, alloc_size, pagesize);
}
}
} else if (!sgen_los_enable_sections_allocator) {
size_t alloc_size = size + sizeof (LOSObject);
if (sgen_memgov_try_alloc_space (alloc_size, SPACE_LOS)) {
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
int alignment = SGEN_ALLOC_ALIGN;
#else
// If we don't use the shadow card table, having a card map to 2 different los objects is invalid
// because once we scan the first object we could clear the card, leading to failure to detect refs
// in the second object. We prevent this by aligning the los object to the card size.
int alignment = CARD_SIZE_IN_BYTES;
#endif
obj = (LOSObject *)sgen_alloc_os_memory_aligned (alloc_size, alignment, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), NULL, MONO_MEM_ACCOUNT_SGEN_LOS);
if (obj)
sgen_los_memory_usage_total += alloc_size;
}
} else {
obj = get_los_section_memory (size + sizeof (LOSObject));
if (obj)