Skip to content

Commit a5136e9

Browse files
lum1n0usclaude
andauthored
Feat: aligned allocation (#4886)
* feat(api): expose aligned allocation through wasm_runtime_aligned_alloc Add public API for aligned memory allocation, exposing the existing mem_allocator_malloc_aligned infrastructure through wasm_export.h. - Add wasm_runtime_aligned_alloc() API declaration with documentation - Implement internal helper wasm_runtime_aligned_alloc_internal() - Add public function with size/alignment validation - POOL mode only, returns NULL for other memory modes - Follows wasm_runtime_malloc() patterns for consistency * fix(tests): resolve memory leak in bh_queue_test_suite and improve message handling * test(mem-alloc): add tests for freeing read-only and freed pointers * test(mem-alloc): add tests for huge allocations and OOM scenarios --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 4b306f0 commit a5136e9

File tree

15 files changed

+1420
-79
lines changed

15 files changed

+1420
-79
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.*
2+
!.gitignore
13

24
.cache
35
.clangd

core/iwasm/common/wasm_memory.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,24 @@ wasm_runtime_free_internal(void *ptr)
10301030
}
10311031
}
10321032

1033+
static inline void *
1034+
wasm_runtime_aligned_alloc_internal(unsigned int size, unsigned int alignment)
1035+
{
1036+
if (memory_mode == MEMORY_MODE_UNKNOWN) {
1037+
LOG_ERROR("wasm_runtime_aligned_alloc failed: memory hasn't been "
1038+
"initialized.\n");
1039+
return NULL;
1040+
}
1041+
1042+
if (memory_mode != MEMORY_MODE_POOL) {
1043+
LOG_ERROR("wasm_runtime_aligned_alloc failed: only supported in POOL "
1044+
"memory mode.\n");
1045+
return NULL;
1046+
}
1047+
1048+
return mem_allocator_malloc_aligned(pool_allocator, size, alignment);
1049+
}
1050+
10331051
void *
10341052
wasm_runtime_malloc(unsigned int size)
10351053
{
@@ -1052,6 +1070,35 @@ wasm_runtime_malloc(unsigned int size)
10521070
return wasm_runtime_malloc_internal(size);
10531071
}
10541072

1073+
void *
1074+
wasm_runtime_aligned_alloc(unsigned int size, unsigned int alignment)
1075+
{
1076+
if (alignment == 0) {
1077+
LOG_WARNING(
1078+
"warning: wasm_runtime_aligned_alloc with zero alignment\n");
1079+
return NULL;
1080+
}
1081+
1082+
if (size == 0) {
1083+
LOG_WARNING("warning: wasm_runtime_aligned_alloc with size zero\n");
1084+
/* Allocate at least alignment bytes (smallest multiple of alignment) */
1085+
size = alignment;
1086+
#if BH_ENABLE_GC_VERIFY != 0
1087+
exit(-1);
1088+
#endif
1089+
}
1090+
1091+
#if WASM_ENABLE_FUZZ_TEST != 0
1092+
if (size >= WASM_MEM_ALLOC_MAX_SIZE) {
1093+
LOG_WARNING(
1094+
"warning: wasm_runtime_aligned_alloc with too large size\n");
1095+
return NULL;
1096+
}
1097+
#endif
1098+
1099+
return wasm_runtime_aligned_alloc_internal(size, alignment);
1100+
}
1101+
10551102
void *
10561103
wasm_runtime_realloc(void *ptr, unsigned int size)
10571104
{

core/iwasm/include/wasm_export.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,22 @@ wasm_runtime_destroy(void);
422422
WASM_RUNTIME_API_EXTERN void *
423423
wasm_runtime_malloc(unsigned int size);
424424

425+
/**
426+
* Allocate memory with specified alignment from runtime memory environment.
427+
* This function mimics aligned_alloc() behavior in WebAssembly context.
428+
*
429+
* Note: Only supported in POOL memory mode. Other modes will return NULL.
430+
* Note: Allocated memory cannot be reallocated with wasm_runtime_realloc().
431+
*
432+
* @param size bytes need to allocate (must be multiple of alignment)
433+
* @param alignment alignment requirement (must be power of 2, >= 8, <= page
434+
* size)
435+
*
436+
* @return the pointer to aligned memory allocated, or NULL on failure
437+
*/
438+
WASM_RUNTIME_API_EXTERN void *
439+
wasm_runtime_aligned_alloc(unsigned int size, unsigned int alignment);
440+
425441
/**
426442
* Reallocate memory from runtime memory environment
427443
*

core/shared/mem-alloc/ems/ems_alloc.c

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,21 @@ alloc_hmu_ex(gc_heap_t *heap, gc_size_t size)
552552
return alloc_hmu(heap, size);
553553
}
554554

555+
/* Convert object pointer to HMU pointer - handles aligned allocations */
556+
hmu_t *
557+
obj_to_hmu(gc_object_t obj)
558+
{
559+
/* Check for aligned allocation magic signature */
560+
if (gc_is_aligned_allocation(obj)) {
561+
/* This is an aligned allocation, read offset */
562+
uint32_t *offset_ptr = ALIGNED_ALLOC_GET_OFFSET_PTR(obj);
563+
return (hmu_t *)((char *)obj - *offset_ptr);
564+
}
565+
566+
/* Normal allocation: standard offset */
567+
return (hmu_t *)((gc_uint8 *)(obj)-OBJ_PREFIX_SIZE) - 1;
568+
}
569+
555570
#if BH_ENABLE_GC_VERIFY == 0
556571
gc_object_t
557572
gc_alloc_vo(void *vheap, gc_size_t size)
@@ -566,7 +581,7 @@ gc_alloc_vo_internal(void *vheap, gc_size_t size, const char *file, int line)
566581
gc_size_t tot_size = 0, tot_size_unaligned;
567582

568583
/* hmu header + prefix + obj + suffix */
569-
tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
584+
tot_size_unaligned = size + OBJ_EXTRA_SIZE;
570585
/* aligned size*/
571586
tot_size = GC_ALIGN_8(tot_size_unaligned);
572587
if (tot_size < size)
@@ -612,6 +627,124 @@ gc_alloc_vo_internal(void *vheap, gc_size_t size, const char *file, int line)
612627
return ret;
613628
}
614629

630+
#if BH_ENABLE_GC_VERIFY == 0
631+
gc_object_t
632+
gc_alloc_vo_aligned(void *vheap, gc_size_t size, gc_size_t alignment)
633+
#else
634+
gc_object_t
635+
gc_alloc_vo_aligned_internal(void *vheap, gc_size_t size, gc_size_t alignment,
636+
const char *file, int line)
637+
#endif
638+
{
639+
gc_heap_t *heap = (gc_heap_t *)vheap;
640+
hmu_t *hmu = NULL;
641+
gc_object_t ret = NULL;
642+
gc_size_t tot_size, tot_size_unaligned;
643+
gc_uint8 *base_obj;
644+
uintptr_t aligned_addr;
645+
uint32_t offset, alignment_log2;
646+
uint32_t max_alignment;
647+
648+
/* Get system page size for maximum alignment check */
649+
max_alignment = (uint32_t)os_getpagesize();
650+
651+
/* Validation */
652+
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
653+
/* Zero or not power of 2 */
654+
return NULL;
655+
}
656+
657+
if (alignment < GC_MIN_ALIGNMENT) {
658+
alignment = GC_MIN_ALIGNMENT;
659+
}
660+
661+
if (alignment > max_alignment) {
662+
/* Exceeds page size */
663+
return NULL;
664+
}
665+
666+
if (size % alignment != 0) {
667+
/* POSIX requirement: size must be multiple of alignment */
668+
return NULL;
669+
}
670+
671+
if (size > SIZE_MAX - GC_ALIGNED_SMALLEST_SIZE(alignment)) {
672+
/* Would overflow */
673+
return NULL;
674+
}
675+
676+
#if BH_ENABLE_GC_CORRUPTION_CHECK != 0
677+
if (heap->is_heap_corrupted) {
678+
LOG_ERROR("[GC_ERROR]Heap is corrupted, allocate memory failed.\n");
679+
return NULL;
680+
}
681+
#endif
682+
683+
/* Calculate total size needed */
684+
tot_size_unaligned = size + OBJ_EXTRA_SIZE + ALIGNED_ALLOC_EXTRA_OVERHEAD
685+
+ (alignment > 8 ? (alignment - 8) : 8);
686+
tot_size = GC_ALIGN_8(tot_size_unaligned);
687+
688+
if (tot_size < size) {
689+
/* Integer overflow */
690+
return NULL;
691+
}
692+
693+
LOCK_HEAP(heap);
694+
695+
hmu = alloc_hmu_ex(heap, tot_size);
696+
if (!hmu)
697+
goto finish;
698+
699+
bh_assert(hmu_get_size(hmu) >= tot_size);
700+
tot_size = hmu_get_size(hmu);
701+
702+
#if GC_STAT_DATA != 0
703+
heap->total_size_allocated += tot_size;
704+
#endif
705+
706+
/* Get base object pointer */
707+
base_obj = (gc_uint8 *)hmu + HMU_SIZE + OBJ_PREFIX_SIZE;
708+
709+
/* Find next aligned address, reserving space for metadata */
710+
aligned_addr =
711+
(((uintptr_t)base_obj + ALIGNED_ALLOC_METADATA_SIZE + alignment - 1)
712+
& ~(uintptr_t)(alignment - 1));
713+
ret = (gc_object_t)aligned_addr;
714+
715+
/* Verify we have enough space */
716+
bh_assert((gc_uint8 *)ret + size + OBJ_SUFFIX_SIZE
717+
<= (gc_uint8 *)hmu + tot_size);
718+
719+
/* Calculate offset from HMU to returned pointer */
720+
offset = (uint32_t)((char *)ret - (char *)hmu);
721+
722+
/* Calculate log2 of alignment for magic value */
723+
alignment_log2 = 0;
724+
while ((1U << alignment_log2) < alignment) {
725+
alignment_log2++;
726+
}
727+
728+
/* Store offset before returned pointer */
729+
*ALIGNED_ALLOC_GET_OFFSET_PTR(ret) = offset;
730+
731+
/* Store magic with encoded alignment */
732+
*ALIGNED_ALLOC_GET_MAGIC_PTR(ret) =
733+
ALIGNED_ALLOC_MAGIC_VALUE | alignment_log2;
734+
735+
/* Initialize HMU */
736+
hmu_set_ut(hmu, HMU_VO);
737+
hmu_unfree_vo(hmu);
738+
739+
#if BH_ENABLE_GC_VERIFY != 0
740+
hmu_init_prefix_and_suffix(hmu, tot_size, file, line);
741+
#endif
742+
743+
finish:
744+
UNLOCK_HEAP(heap);
745+
return ret;
746+
}
747+
615748
#if BH_ENABLE_GC_VERIFY == 0
616749
gc_object_t
617750
gc_realloc_vo(void *vheap, void *ptr, gc_size_t size)
@@ -644,6 +777,13 @@ gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size, const char *file,
644777
}
645778
#endif
646779

780+
/* Check if this is an aligned allocation - not supported */
781+
if (gc_is_aligned_allocation(obj_old)) {
782+
LOG_ERROR("[GC_ERROR]gc_realloc_vo does not support aligned "
783+
"allocations\n");
784+
return NULL;
785+
}
786+
647787
if (obj_old) {
648788
hmu_old = obj_to_hmu(obj_old);
649789
tot_size_old = hmu_get_size(hmu_old);

core/shared/mem-alloc/ems/ems_gc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ gc_alloc_vo(void *heap, gc_size_t size);
193193
gc_object_t
194194
gc_realloc_vo(void *heap, void *ptr, gc_size_t size);
195195

196+
gc_object_t
197+
gc_alloc_vo_aligned(void *heap, gc_size_t size, gc_size_t alignment);
198+
196199
int
197200
gc_free_vo(void *heap, gc_object_t obj);
198201

@@ -213,6 +216,10 @@ gc_object_t
213216
gc_realloc_vo_internal(void *heap, void *ptr, gc_size_t size, const char *file,
214217
int line);
215218

219+
gc_object_t
220+
gc_alloc_vo_aligned_internal(void *heap, gc_size_t size, gc_size_t alignment,
221+
const char *file, int line);
222+
216223
int
217224
gc_free_vo_internal(void *heap, gc_object_t obj, const char *file, int line);
218225

@@ -231,6 +238,9 @@ gc_free_wo_internal(void *vheap, void *ptr, const char *file, int line);
231238
#define gc_realloc_vo(heap, ptr, size) \
232239
gc_realloc_vo_internal(heap, ptr, size, __FILE__, __LINE__)
233240

241+
#define gc_alloc_vo_aligned(heap, size, alignment) \
242+
gc_alloc_vo_aligned_internal(heap, size, alignment, __FILE__, __LINE__)
243+
234244
#define gc_free_vo(heap, obj) \
235245
gc_free_vo_internal(heap, obj, __FILE__, __LINE__)
236246

0 commit comments

Comments
 (0)