|
|
|
@ -2891,6 +2891,10 @@ typedef struct upb_ArenaInternal { |
|
|
|
|
// block.
|
|
|
|
|
uintptr_t block_alloc; |
|
|
|
|
|
|
|
|
|
// The cleanup for the allocator. This is called after all the blocks are
|
|
|
|
|
// freed in an arena.
|
|
|
|
|
upb_AllocCleanupFunc* upb_alloc_cleanup; |
|
|
|
|
|
|
|
|
|
// When multiple arenas are fused together, each arena points to a parent
|
|
|
|
|
// arena (root points to itself). The root tracks how many live arenas
|
|
|
|
|
// reference it.
|
|
|
|
@ -3158,6 +3162,7 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc) { |
|
|
|
|
upb_Atomic_Init(&a->body.next, NULL); |
|
|
|
|
upb_Atomic_Init(&a->body.tail, &a->body); |
|
|
|
|
upb_Atomic_Init(&a->body.blocks, NULL); |
|
|
|
|
a->body.upb_alloc_cleanup = NULL; |
|
|
|
|
|
|
|
|
|
_upb_Arena_AddBlock(&a->head, mem, n); |
|
|
|
|
|
|
|
|
@ -3196,6 +3201,7 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { |
|
|
|
|
upb_Atomic_Init(&a->body.next, NULL); |
|
|
|
|
upb_Atomic_Init(&a->body.tail, &a->body); |
|
|
|
|
upb_Atomic_Init(&a->body.blocks, NULL); |
|
|
|
|
a->body.upb_alloc_cleanup = NULL; |
|
|
|
|
|
|
|
|
|
a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); |
|
|
|
|
a->head.UPB_PRIVATE(ptr) = mem; |
|
|
|
@ -3214,6 +3220,7 @@ static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { |
|
|
|
|
(upb_ArenaInternal*)upb_Atomic_Load(&ai->next, memory_order_acquire); |
|
|
|
|
upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai); |
|
|
|
|
upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); |
|
|
|
|
upb_AllocCleanupFunc* alloc_cleanup = *ai->upb_alloc_cleanup; |
|
|
|
|
while (block != NULL) { |
|
|
|
|
// Load first since we are deleting block.
|
|
|
|
|
upb_MemBlock* next_block = |
|
|
|
@ -3221,6 +3228,9 @@ static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { |
|
|
|
|
upb_free(block_alloc, block); |
|
|
|
|
block = next_block; |
|
|
|
|
} |
|
|
|
|
if (alloc_cleanup != NULL) { |
|
|
|
|
alloc_cleanup(block_alloc); |
|
|
|
|
} |
|
|
|
|
ai = next_arena; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -3285,6 +3295,12 @@ static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent, |
|
|
|
|
upb_Atomic_Store(&parent->tail, parent_tail, memory_order_relaxed); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_Arena_SetAllocCleanup(upb_Arena* a, upb_AllocCleanupFunc* func) { |
|
|
|
|
upb_ArenaInternal* ai = upb_Arena_Internal(a); |
|
|
|
|
UPB_ASSERT(ai->upb_alloc_cleanup == NULL); |
|
|
|
|
ai->upb_alloc_cleanup = func; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static upb_ArenaInternal* _upb_Arena_DoFuse(const upb_Arena* a1, |
|
|
|
|
const upb_Arena* a2, |
|
|
|
|
uintptr_t* ref_delta) { |
|
|
|
|