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

View File

@ -86,11 +86,11 @@ hmu_verify(void *vheap, hmu_t *hmu);
#define GC_MIN_ALIGNMENT 8 #define GC_MIN_ALIGNMENT 8
#endif #endif
#define GC_SMALLEST_SIZE \ /* Smallest allocation size for normal allocations
GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8) * The +8 ensures minimum allocation size for tree node structure */
#define GC_GET_REAL_SIZE(x) \ #define GC_SMALLEST_SIZE GC_ALIGN_8(OBJ_EXTRA_SIZE + 8)
GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE \
+ (((x) > 8) ? (x) : 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 * Low Address High Address
* *
* HMU Header Padding Magic + Offset Aligned Data Padding * HMU Header Padding Offset Magic Aligned Data Padding
* (meta) (0-align) (4 bytes) (size) (overhead) * (4 bytes) (variable)(4 bytes)(4 bytes) (size) (overhead)
* *
* * 8 bytes
* * hmu user_ptr (returned, aligned)
* magic_ptr 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: * Constraints and Limitations:
* ---------------------------- * ----------------------------
@ -182,10 +186,35 @@ hmu_verify(void *vheap, hmu_t *hmu);
* void *new_ptr = wasm_runtime_realloc(ptr, 512); // Returns NULL! * 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 */ /* Aligned allocation magic markers */
#define ALIGNED_ALLOC_MAGIC_MASK 0xFFFF0000 #define ALIGNED_ALLOC_MAGIC_MASK 0xFFFF0000
#define ALIGNED_ALLOC_MAGIC_VALUE 0xA11C0000 #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. * Check if a gc_object was allocated with alignment requirements.
* *
@ -202,7 +231,7 @@ gc_is_aligned_allocation(gc_object_t obj)
if (!obj) if (!obj)
return false; 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) return ((*magic_ptr & ALIGNED_ALLOC_MAGIC_MASK)
== ALIGNED_ALLOC_MAGIC_VALUE); == ALIGNED_ALLOC_MAGIC_VALUE);
} }