Fix ems allocator unaligned memory access on riscv64 (#2140)

Make `hmu_tree_node` struct packed and add 4 padding bytes before `kfc_tree_root_buf`
field in `gc_heap_struct` struct to ensure the `left/right/parent` fields in `hmu_tree_node`
are 8-byte aligned on the 64-bit target which doesn't support unaligned memory access.

Fix the issue reported in #2136.
This commit is contained in:
Wenyong Huang
2023-04-26 18:13:11 +08:00
committed by GitHub
parent 15139d2bb8
commit 5c497e5a14
3 changed files with 90 additions and 20 deletions

View File

@ -25,7 +25,7 @@ static bool
remove_tree_node(gc_heap_t *heap, hmu_tree_node_t *p)
{
hmu_tree_node_t *q = NULL, **slot = NULL, *parent;
hmu_tree_node_t *root = &heap->kfc_tree_root;
hmu_tree_node_t *root = heap->kfc_tree_root;
gc_uint8 *base_addr = heap->base_addr;
gc_uint8 *end_addr = base_addr + heap->current_size;
@ -38,13 +38,17 @@ remove_tree_node(gc_heap_t *heap, hmu_tree_node_t *p)
goto fail;
}
/* get the slot which holds pointer to node p*/
/* get the slot which holds pointer to node p */
if (p == p->parent->right) {
slot = &p->parent->right;
/* Don't use `slot = &p->parent->right` to avoid compiler warning */
slot = (hmu_tree_node_t **)((uint8 *)p->parent
+ offsetof(hmu_tree_node_t, right));
}
else if (p == p->parent->left) {
/* p should be a child of its parent*/
slot = &p->parent->left;
/* p should be a child of its parent */
/* Don't use `slot = &p->parent->left` to avoid compiler warning */
slot = (hmu_tree_node_t **)((uint8 *)p->parent
+ offsetof(hmu_tree_node_t, left));
}
else {
goto fail;
@ -241,7 +245,7 @@ gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
node->left = node->right = node->parent = NULL;
/* find proper node to link this new node to */
root = &heap->kfc_tree_root;
root = heap->kfc_tree_root;
tp = root;
bh_assert(tp->size < size);
while (1) {
@ -289,6 +293,7 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size)
uint32 node_idx = 0, init_node_idx = 0;
hmu_tree_node_t *root = NULL, *tp = NULL, *last_tp = NULL;
hmu_t *next, *rest;
uintptr_t tp_ret;
bh_assert(gci_is_heap_valid(heap));
bh_assert(size > 0 && !(size & 7));
@ -354,7 +359,7 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size)
}
/* need to find a node in tree*/
root = &heap->kfc_tree_root;
root = heap->kfc_tree_root;
/* find the best node*/
bh_assert(root);
@ -402,7 +407,8 @@ alloc_hmu(gc_heap_t *heap, gc_size_t size)
heap->highmark_size = heap->current_size - heap->total_free_size;
hmu_set_size((hmu_t *)last_tp, size);
return (hmu_t *)last_tp;
tp_ret = (uintptr_t)last_tp;
return (hmu_t *)tp_ret;
}
return NULL;