feat(mem-alloc): enhance aligned allocation with metadata handling

This commit is contained in:
liang.he@intel.com 2026-04-16 13:19:26 +08:00
parent 5ac967ca2b
commit 6042a61092
2 changed files with 54 additions and 25 deletions

View File

@ -559,7 +559,7 @@ obj_to_hmu(gc_object_t obj)
/* Check for aligned allocation magic signature */
if (gc_is_aligned_allocation(obj)) {
/* This is an aligned allocation, read offset */
uint32_t *offset_ptr = (uint32_t *)((char *)obj - 8);
uint32_t *offset_ptr = ALIGNED_ALLOC_GET_OFFSET_PTR(obj);
return (hmu_t *)((char *)obj - *offset_ptr);
}
@ -581,7 +581,7 @@ gc_alloc_vo_internal(void *vheap, gc_size_t size, const char *file, int line)
gc_size_t tot_size = 0, tot_size_unaligned;
/* hmu header + prefix + obj + suffix */
tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
tot_size_unaligned = size + OBJ_EXTRA_SIZE;
/* aligned size*/
tot_size = GC_ALIGN_8(tot_size_unaligned);
if (tot_size < size)
@ -668,8 +668,7 @@ gc_alloc_vo_aligned_internal(void *vheap, gc_size_t size, gc_size_t alignment,
return NULL;
}
if (size > SIZE_MAX - alignment - HMU_SIZE - OBJ_PREFIX_SIZE
- OBJ_SUFFIX_SIZE - 8) {
if (size > SIZE_MAX - GC_ALIGNED_SMALLEST_SIZE(alignment)) {
/* Would overflow */
return NULL;
}
@ -682,8 +681,8 @@ gc_alloc_vo_aligned_internal(void *vheap, gc_size_t size, gc_size_t alignment,
#endif
/* Calculate total size needed */
tot_size_unaligned =
HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE + alignment - 1 + 8;
tot_size_unaligned = size + OBJ_EXTRA_SIZE + ALIGNED_ALLOC_EXTRA_OVERHEAD
+ (alignment > 8 ? (alignment - 8) : 8);
tot_size = GC_ALIGN_8(tot_size_unaligned);
if (tot_size < size) {
@ -707,8 +706,9 @@ gc_alloc_vo_aligned_internal(void *vheap, gc_size_t size, gc_size_t alignment,
/* Get base object pointer */
base_obj = (gc_uint8 *)hmu + HMU_SIZE + OBJ_PREFIX_SIZE;
/* Find next aligned address, leaving 8 bytes for metadata */
aligned_addr = (((uintptr_t)base_obj + 8 + alignment - 1)
/* Find next aligned address, reserving space for metadata */
aligned_addr =
(((uintptr_t)base_obj + ALIGNED_ALLOC_METADATA_SIZE + alignment - 1)
& ~(uintptr_t)(alignment - 1));
ret = (gc_object_t)aligned_addr;
@ -725,11 +725,11 @@ gc_alloc_vo_aligned_internal(void *vheap, gc_size_t size, gc_size_t alignment,
alignment_log2++;
}
/* Store offset 8 bytes before returned pointer */
*((uint32_t *)((char *)ret - 8)) = offset;
/* Store offset before returned pointer */
*ALIGNED_ALLOC_GET_OFFSET_PTR(ret) = offset;
/* Store magic with encoded alignment */
*((uint32_t *)((char *)ret - 4)) =
*ALIGNED_ALLOC_GET_MAGIC_PTR(ret) =
ALIGNED_ALLOC_MAGIC_VALUE | alignment_log2;
/* Initialize HMU */

View File

@ -86,11 +86,11 @@ hmu_verify(void *vheap, hmu_t *hmu);
#define GC_MIN_ALIGNMENT 8
#endif
#define GC_SMALLEST_SIZE \
GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8)
#define GC_GET_REAL_SIZE(x) \
GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE \
+ (((x) > 8) ? (x) : 8))
/* Smallest allocation size for normal allocations
* The +8 ensures minimum allocation size for tree node structure */
#define GC_SMALLEST_SIZE GC_ALIGN_8(OBJ_EXTRA_SIZE + 8)
#define GC_GET_REAL_SIZE(x) GC_ALIGN_8(OBJ_EXTRA_SIZE + (((x) > 8) ? (x) : 8))
/*
* ============================================================================
@ -150,13 +150,17 @@ hmu_verify(void *vheap, hmu_t *hmu);
* ----------------------
*
* Low Address High Address
*
* HMU Header Padding Magic + Offset Aligned Data Padding
* (meta) (0-align) (4 bytes) (size) (overhead)
*
*
*
* magic_ptr user_ptr (returned, aligned)
*
* HMU Header Padding Offset Magic Aligned Data Padding
* (4 bytes) (variable)(4 bytes)(4 bytes) (size) (overhead)
*
* 8 bytes
* hmu user_ptr (returned, aligned)
*
* Padding is variable-length to satisfy alignment constraint:
* align_up(HMU_SIZE + ALIGNED_ALLOC_METADATA_SIZE, alignment)
* For alignment >= 12: HMU_SIZE + padding + 8 = alignment
* For alignment < 12: HMU_SIZE + padding + 8 = round_up(12, alignment)
*
* Constraints and Limitations:
* ----------------------------
@ -182,10 +186,35 @@ hmu_verify(void *vheap, hmu_t *hmu);
* void *new_ptr = wasm_runtime_realloc(ptr, 512); // Returns NULL!
*/
/* Aligned allocation constants */
/* Size of offset field before aligned ptr */
#define ALIGNED_ALLOC_OFFSET_SIZE 4
/* Size of magic marker before aligned ptr */
#define ALIGNED_ALLOC_MAGIC_SIZE 4
/* Total: 8 bytes */
#define ALIGNED_ALLOC_METADATA_SIZE \
(ALIGNED_ALLOC_OFFSET_SIZE + ALIGNED_ALLOC_MAGIC_SIZE)
/* Aligned allocation magic markers */
#define ALIGNED_ALLOC_MAGIC_MASK 0xFFFF0000
#define ALIGNED_ALLOC_MAGIC_VALUE 0xA11C0000
/* Get magic pointer from aligned object pointer */
#define ALIGNED_ALLOC_GET_MAGIC_PTR(obj) \
((uint32_t *)((char *)(obj)-ALIGNED_ALLOC_MAGIC_SIZE))
/* Get offset pointer from aligned object pointer */
#define ALIGNED_ALLOC_GET_OFFSET_PTR(obj) \
((uint32_t *)((char *)(obj)-ALIGNED_ALLOC_METADATA_SIZE))
/* Extra overhead for aligned allocations beyond normal OBJ_EXTRA_SIZE */
#define ALIGNED_ALLOC_EXTRA_OVERHEAD ALIGNED_ALLOC_METADATA_SIZE
/* Smallest allocation size for aligned allocations */
#define GC_ALIGNED_SMALLEST_SIZE(alignment) \
GC_ALIGN_8(OBJ_EXTRA_SIZE + ALIGNED_ALLOC_METADATA_SIZE \
+ ((alignment) > 8 ? (alignment - 8) : 8))
/**
* Check if a gc_object was allocated with alignment requirements.
*
@ -202,7 +231,7 @@ gc_is_aligned_allocation(gc_object_t obj)
if (!obj)
return false;
uint32_t *magic_ptr = (uint32_t *)((char *)obj - 4);
uint32_t *magic_ptr = ALIGNED_ALLOC_GET_MAGIC_PTR(obj);
return ((*magic_ptr & ALIGNED_ALLOC_MAGIC_MASK)
== ALIGNED_ALLOC_MAGIC_VALUE);
}