Files
UnrealEngine/Engine/Source/Runtime/SymsLib/syms/overrides/syms_default_arena.c
2025-05-18 13:04:45 +08:00

185 lines
4.7 KiB
C

// Copyright Epic Games, Inc. All Rights Reserved.
#ifndef SYMS_DEFAULT_ARENA_C
#define SYMS_DEFAULT_ARENA_C
SYMS_OVERRIDE_FUNC SYMS_DefArena*
syms_arena_def_alloc__sized(SYMS_U64 res, SYMS_U64 cmt){
SYMS_ASSERT(SYMS_ARENA_HEADER_SIZE < cmt && cmt <= res);
SYMS_Arena *result = 0;
void *memory = syms_mem_reserve(res);
if (memory != 0){
if (syms_mem_commit(memory, cmt)){
result = (SYMS_Arena*)memory;
result->prev = 0;
result->current = result;
result->base_pos = 0;
result->pos = SYMS_ARENA_HEADER_SIZE;
result->cmt = cmt;
result->cap = res;
result->align = 8;
result->dev = 0;
}
else{
syms_mem_release(memory, res);
}
}
return(result);
}
SYMS_OVERRIDE_FUNC SYMS_DefArena*
syms_arena_def_alloc(void){
SYMS_DefArena *result = syms_arena_def_alloc__sized(SYMS_ARENA_RESERVE_SIZE, SYMS_ARENA_COMMIT_SIZE);
return(result);
}
SYMS_OVERRIDE_FUNC void
syms_arena_def_release(SYMS_DefArena *arena){
for (SYMS_DefArena *node = arena->current, *prev = 0;
node != 0;
node = prev){
prev = node->prev;
syms_mem_release(node, node->cap);
}
}
#define SYMS_ARENA_VERY_LARGE ((SYMS_ARENA_RESERVE_SIZE - SYMS_ARENA_HEADER_SIZE)/2) + 1
SYMS_OVERRIDE_FUNC void*
syms_arena_def_push(SYMS_DefArena *arena, SYMS_U64 size){
void *result = 0;
// get new pos
SYMS_Arena *current = arena->current;
SYMS_U64 pos_aligned = SYMS_AlignPow2(current->pos, arena->align);
SYMS_U64 pos_new = pos_aligned + size;
// check cap
if (current->cap < pos_new){
// normal growth path
SYMS_Arena *new_block = 0;
if (size < SYMS_ARENA_VERY_LARGE){
new_block = syms_arena_def_alloc();
}
// "very large" growth path
else{
SYMS_U64 size_aligned = SYMS_AlignPow2(size + SYMS_ARENA_HEADER_SIZE, (4 << 10));
new_block = syms_arena_def_alloc__sized(size_aligned, size_aligned);
}
// connect block to chain
if (new_block != 0){
new_block->base_pos = current->base_pos + current->cap;
SYMS_StackPush_N(arena->current, new_block, prev);
// recompute the new pos
current = new_block;
pos_aligned = SYMS_AlignPow2(current->pos, arena->align);
pos_new = pos_aligned + size;
}
}
// cap big enough?
if (current->cap >= pos_new){
// cmt too small?
if (current->cmt < pos_new){
// get new cmt
SYMS_U64 cmt_new_unclamped = SYMS_AlignPow2(pos_new, SYMS_ARENA_COMMIT_SIZE);
SYMS_U64 cmt_new = SYMS_ClampTop(cmt_new_unclamped, current->cap);
SYMS_U64 cmt_size = cmt_new - current->cmt;
// try commit
if (syms_mem_commit((SYMS_U8*)current + current->cmt, cmt_size)){
current->cmt = cmt_new;
}
}
// cmt big enough?
if (current->cmt >= pos_new){
// get result & advance pos
result = (SYMS_U8*)current + pos_aligned;
current->pos = pos_new;
}
}
SYMS_ASSERT(arena->current != 0);
// dev
#if SYMS_ENABLE_DEV_ARENA
syms_arena_dev_push__impl(arena, size, result);
#endif
return(result);
}
SYMS_OVERRIDE_FUNC SYMS_U64
syms_arena_def_pos(SYMS_Arena *arena){
SYMS_Arena *current = arena->current;
SYMS_U64 result = current->base_pos + current->pos;
return(result);
}
SYMS_OVERRIDE_FUNC void
syms_arena_def_pop_to(SYMS_DefArena *arena, SYMS_U64 pos_unclamped){
SYMS_U64 big_pos = SYMS_ClampBot(SYMS_ARENA_HEADER_SIZE, pos_unclamped);
// unroll the chain
SYMS_Arena *current = arena->current;
for (SYMS_Arena *prev = 0;
current->base_pos >= big_pos;
current = prev){
prev = current->prev;
syms_mem_release(current, current->cap);
}
arena->current = current;
// fix the pos
{
SYMS_U64 pos_unclamped = big_pos - current->base_pos;
SYMS_U64 pos = SYMS_ClampBot(SYMS_ARENA_HEADER_SIZE, pos_unclamped);
if (pos < current->pos){
current->pos = pos;
}
}
SYMS_ASSERT(arena->current != 0);
// dev
#if SYMS_ENABLE_DEV_ARENA
syms_arena_dev_pop_to__impl(arena, pos_unclamped);
#endif
}
SYMS_OVERRIDE_FUNC void
syms_arena_def_set_auto_align(SYMS_DefArena *arena, SYMS_U64 pow2_align){
arena->align = pow2_align;
}
SYMS_OVERRIDE_FUNC void
syms_arena_def_absorb(SYMS_DefArena *arena, SYMS_DefArena *sub){
// base adjustment
SYMS_DefArena *current = arena->current;
SYMS_U64 base_adjust = current->base_pos + current->cap;
for (SYMS_DefArena *node = sub->current;
node != 0;
node = node->prev){
node->base_pos += base_adjust;
}
// attach sub to arena
sub->prev = arena->current;
arena->current = sub->current;
sub->current = sub;
// dev
#if SYMS_ENABLE_DEV_ARENA
syms_arena_dev_absorb__impl(arena, sub);
#endif
}
#endif //SYMS_DEFAULT_ARENA_C