mirror of
https://github.com/Ed94/WATL_Exercise.git
synced 2025-11-09 01:59:18 -08:00
WIP(untesed, not-compiled): Still curating, Ai code was terrible, scrapping most of it.
This commit is contained in:
@@ -843,16 +843,17 @@ I_ U8 varena__make__u(U8 reserve_size, U8 commit_size, U8 flags, U8 base_addr) {
|
||||
return base;
|
||||
}
|
||||
void varena__push__u(U8 arena, U8 amount, U8 type_width, U8 alignment, U8 result) {
|
||||
if (result == null || arena == null) { return; }
|
||||
if (amount == 0) { struct_zero(Slice_Mem, result); return; }
|
||||
U8 reg align = alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT;
|
||||
U8 reg requested_size = amount * type_width;
|
||||
assert(result != null);
|
||||
assert(arena != null);
|
||||
if (amount == 0) { struct_zero(Slice_Mem, result); return; }
|
||||
U8 align = alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT;
|
||||
U8 requested_size = amount * type_width;
|
||||
U8 reg aligned_size = align_pow2(requested_size, align);
|
||||
U8_R reg commit_used = u8_r(arena + offset_of(VArena, commit_used ));
|
||||
U8 reg reserve_left = u8_r(arena + offset_of(VArena, reserve ))[0] - commit_used[0];
|
||||
if (aligned_size > reserve_left) { struct_zero(Slice_Mem, result); return; }
|
||||
U8 reg committed = u8_r(arena + offset_of(VArena, committed ))[0];
|
||||
U8 reg commit_left = committed - commit_used[0];
|
||||
U8 commit_left = committed - commit_used[0];
|
||||
if (commit_left < aligned_size) {
|
||||
U8 reg commit_size = u8_r(arena + offset_of(VArena, commit_size))[0];
|
||||
U8 reg next_commit = reserve_left > aligned_size ? max(commit_size, aligned_size) : reserve_left;
|
||||
@@ -872,47 +873,28 @@ void varena__push__u(U8 arena, U8 amount, U8 type_width, U8 alignment, U8 result
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(current_offset, requested_size));
|
||||
}
|
||||
}
|
||||
inline
|
||||
void varena__grow__u(U8 result, U8 arena, U8 old_ptr, U8 old_len, U8 requested_size, U8 alignment, B4 should_zero) {
|
||||
if (result == null || arena == null) { return; }
|
||||
if (old_ptr == 0 || requested_size <= old_len) {
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(old_ptr, requested_size));
|
||||
return;
|
||||
}
|
||||
U8_R reg commit_used = u8_r(arena + offset_of(VArena, commit_used));
|
||||
U8 reg reserve_start = u8_r(arena + offset_of(VArena, reserve_start))[0];
|
||||
U8 reg current_offset = reserve_start + commit_used[0];
|
||||
if (old_ptr + old_len != current_offset) {
|
||||
struct_zero(Slice_Mem, result);
|
||||
return;
|
||||
}
|
||||
U8 reg grow_amount = requested_size - old_len;
|
||||
uvar(Slice_Mem, extra) = {0};
|
||||
varena__push__u(arena, grow_amount, 1, alignment, u8_(extra));
|
||||
U8 extra_ptr = u8_r(extra + offset_of(Slice_Mem, ptr))[0];
|
||||
U8 extra_len = u8_r(extra + offset_of(Slice_Mem, len))[0];
|
||||
if (extra_ptr == 0) {
|
||||
struct_zero(Slice_Mem, result);
|
||||
return;
|
||||
}
|
||||
U8 reg new_len = old_len + extra_len;
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(old_ptr, new_len));
|
||||
if (should_zero && grow_amount != 0) {
|
||||
memory_zero(old_ptr + old_len, grow_amount);
|
||||
}
|
||||
}
|
||||
assert(arena != null);
|
||||
assert(result != null);
|
||||
|
||||
}
|
||||
void varena__shrink__u(U8 result, U8 arena, U8 old_ptr, U8 old_len, U8 requested_size, U8 alignment) {
|
||||
|
||||
}
|
||||
inline
|
||||
I_ void varena_release__u(U8 arena) {
|
||||
if (arena == null) { return; }
|
||||
assert(arena != null);
|
||||
os_vmem_release__u(arena, u8_r(arena + offset_of(VArena, reserve))[0]);
|
||||
}
|
||||
I_ void varena_reset__u(U8 arena) {
|
||||
if (arena == null) { return; }
|
||||
assert(arena != null);
|
||||
u8_r(arena + offset_of(VArena, commit_used))[0] = 0;
|
||||
}
|
||||
I_ void varena_rewind__u(U8 arena, U8 sp_type_sig, U8 sp_slot) {
|
||||
if (arena == null) { return; }
|
||||
assert(arena != null);
|
||||
assert(sp_type_sig == (U8) varena_allocator_proc);
|
||||
U8 header = varena__header_size();
|
||||
U8 reg header = varena__header_size();
|
||||
if (sp_slot < header) { sp_slot = header; }
|
||||
u8_r(arena + offset_of(VArena, commit_used))[0] = sp_slot;
|
||||
}
|
||||
@@ -922,114 +904,67 @@ I_ void varena_save__u(U8 arena, U8 sp_addr) {
|
||||
u8_r(sp_addr + offset_of(AllocatorSP, slot ))[0] = u8_r(arena + offset_of(VArena, commit_used))[0];
|
||||
}
|
||||
|
||||
void varena__shrink__u(U8 result, U8 arena, U8 old_ptr, U8 old_len, U8 requested_size, U8 alignment) {
|
||||
if (result == null || arena == null) { return; }
|
||||
if (old_ptr == 0 || requested_size >= old_len) {
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(old_ptr, min(requested_size, old_len)));
|
||||
return;
|
||||
}
|
||||
U8_R reg commit_used = u8_r(arena + offset_of(VArena, commit_used));
|
||||
U8 reg reserve_start = u8_r(arena + offset_of(VArena, reserve_start))[0];
|
||||
U8 reg current_offset = reserve_start + commit_used[0];
|
||||
if (old_ptr + old_len != current_offset) {
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(old_ptr, requested_size));
|
||||
return;
|
||||
}
|
||||
U8 reg aligned_original = align_pow2(old_len, MEMORY_ALIGNMENT_DEFAULT);
|
||||
U8 reg aligned_new = align_pow2(requested_size, alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
if (aligned_new > aligned_original) { aligned_new = aligned_original; }
|
||||
commit_used[0] -= (aligned_original - aligned_new);
|
||||
struct_copy(Slice_Mem, result, (U8)& slice_mem(old_ptr, requested_size));
|
||||
}
|
||||
|
||||
I_ VArena* varena__make(Opts_varena_make* opts) {
|
||||
assert(opts != nullptr);
|
||||
return cast(VArena*, varena__make__u(opts->reserve_size, opts->commit_size, opts->flags, opts->base_addr));
|
||||
}
|
||||
|
||||
Slice_Mem varena__push(VArena_R arena, U8 amount, U8 type_width, Opts_varena* opts) {
|
||||
I_ Slice_Mem varena__push(VArena_R arena, U8 amount, U8 type_width, Opts_varena* opts) {
|
||||
Slice_Mem result;
|
||||
varena__push__u(u8_(arena), amount, type_width, opts ? opts->alignment : 0, u8_(& result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void varena_release(VArena_R arena) { varena_release__u(u8_(arena)); }
|
||||
void varena_reset (VArena_R arena) { varena_reset__u (u8_(arena)); }
|
||||
|
||||
void varena_rewind(VArena_R arena, AllocatorSP save_point) {
|
||||
varena_rewind__u(u8_(arena), u8_(save_point.type_sig), save_point.slot);
|
||||
}
|
||||
|
||||
Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size, Opts_varena* opts) {
|
||||
I_ Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size, Opts_varena* opts) {
|
||||
Slice_Mem result;
|
||||
varena__shrink__u(u8_(& result), u8_(arena), old_allocation.ptr, old_allocation.len, requested_size, opts ? opts->alignment : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
AllocatorSP varena_save(VArena_R arena) {
|
||||
AllocatorSP sp;
|
||||
varena_save__u(u8_(arena), u8_(& sp));
|
||||
return sp;
|
||||
I_ void varena_release(VArena_R arena) { varena_release__u(u8_(arena)); }
|
||||
I_ void varena_reset (VArena_R arena) { varena_reset__u (u8_(arena)); }
|
||||
|
||||
I_ void varena_rewind (VArena_R arena, AllocatorSP save_point) {
|
||||
varena_rewind__u(u8_(arena), u8_(save_point.type_sig), save_point.slot);
|
||||
}
|
||||
I_ AllocatorSP varena_save(VArena_R arena) { AllocatorSP sp; varena_save__u(u8_(arena), u8_(& sp)); return sp; }
|
||||
|
||||
void varena_allocator_proc(U8 arena, U8 requested_size, U8 alignment, U8 old_ptr, U8 old_len, U4 op, U8 out_addr)
|
||||
{
|
||||
AllocatorProc_Out* out = cast(AllocatorProc_Out*, out_addr);
|
||||
U8 allocation_addr = out_addr ? out_addr + offset_of(AllocatorProc_Out, allocation) : 0;
|
||||
if (arena == null) {
|
||||
if (allocation_addr) { struct_zero(Slice_Mem, allocation_addr); }
|
||||
return;
|
||||
}
|
||||
assert(arena != null);
|
||||
assert(out_addr != null);
|
||||
U8 out_allocation = out_addr ? out_addr + offset_of(AllocatorProc_Out, allocation) : 0;
|
||||
switch (op)
|
||||
{
|
||||
case AllocatorOp_Alloc:
|
||||
case AllocatorOp_Alloc_NoZero:
|
||||
if (allocation_addr) {
|
||||
varena__push__u(arena, requested_size, 1, alignment, allocation_addr);
|
||||
if (op == AllocatorOp_Alloc) {
|
||||
U8 ptr = u8_r(allocation_addr + offset_of(Slice_Mem, ptr))[0];
|
||||
U8 len = u8_r(allocation_addr + offset_of(Slice_Mem, len))[0];
|
||||
if (ptr && len) { memory_zero(ptr, len); }
|
||||
}
|
||||
varena__push__u(arena, requested_size, 1, alignment, out_allocation);
|
||||
if (op == AllocatorOp_Alloc) {
|
||||
U8 ptr = u8_r(out_allocation + offset_of(Slice_Mem, ptr))[0];
|
||||
U8 len = u8_r(out_allocation + offset_of(Slice_Mem, len))[0];
|
||||
if (ptr && len) { memory_zero(ptr, len); }
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case AllocatorOp_Free:
|
||||
break;
|
||||
|
||||
case AllocatorOp_Reset:
|
||||
varena_reset__u(arena);
|
||||
break;
|
||||
case AllocatorOp_Free: break;
|
||||
case AllocatorOp_Reset: varena_reset__u(arena); break;
|
||||
|
||||
case AllocatorOp_Grow:
|
||||
case AllocatorOp_Grow_NoZero:
|
||||
if (allocation_addr) {
|
||||
varena__grow__u(allocation_addr, arena, old_ptr, old_len, requested_size, alignment, op - AllocatorOp_Grow_NoZero);
|
||||
}
|
||||
break;
|
||||
|
||||
varena__grow__u(out_allocation, arena, old_ptr, old_len, requested_size, alignment, op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
case AllocatorOp_Shrink:
|
||||
if (allocation_addr) {
|
||||
varena__shrink__u(allocation_addr, arena, old_ptr, old_len, requested_size, alignment);
|
||||
}
|
||||
break;
|
||||
varena__shrink__u(out_allocation, arena, old_ptr, old_len, requested_size, alignment);
|
||||
break;
|
||||
|
||||
case AllocatorOp_Rewind:
|
||||
varena_rewind__u(arena, old_ptr, old_len);
|
||||
break;
|
||||
|
||||
case AllocatorOp_SavePoint:
|
||||
if (out_addr) { varena_save__u(arena, out_addr + offset_of(AllocatorProc_Out, save_point)); }
|
||||
break;
|
||||
case AllocatorOp_Rewind: varena_rewind__u(arena, old_ptr, old_len); break;
|
||||
case AllocatorOp_SavePoint: varena_save__u (arena, out_addr + offset_of(AllocatorProc_Out, save_point)); break;
|
||||
|
||||
case AllocatorOp_Query:
|
||||
if (out_addr) {
|
||||
u4_r(out_addr + offset_of(AllocatorQueryInfo, features))[0] =
|
||||
AllocatorQuery_Alloc
|
||||
| AllocatorQuery_Reset
|
||||
| AllocatorQuery_Resize
|
||||
| AllocatorQuery_Rewind;
|
||||
U8 reserve = u8_r(arena + offset_of(VArena, reserve))[0];
|
||||
U8 reserve = u8_r(arena + offset_of(VArena, reserve ))[0];
|
||||
U8 committed = u8_r(arena + offset_of(VArena, committed))[0];
|
||||
U8 max_alloc = (reserve > committed) ? (reserve - committed) : 0;
|
||||
u8_r(out_addr + offset_of(AllocatorQueryInfo, max_alloc))[0] = max_alloc;
|
||||
@@ -1037,11 +972,7 @@ void varena_allocator_proc(U8 arena, U8 requested_size, U8 alignment, U8 old_ptr
|
||||
u8_r(out_addr + offset_of(AllocatorQueryInfo, left ))[0] = max_alloc;
|
||||
AllocatorSP sp = { .type_sig = varena_allocator_proc, .slot = u8_r(arena + offset_of(VArena, commit_used))[0] };
|
||||
struct_copy(AllocatorSP, out_addr + offset_of(AllocatorQueryInfo, save_point), (U8)& sp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma endregion VArena
|
||||
|
||||
@@ -473,7 +473,7 @@ VArena* varena__make(Opts_varena_make*R_ opts);
|
||||
finline void varena_release(VArena_R arena);
|
||||
finline void varena_rewind (VArena_R arena, AllocatorSP save_point);
|
||||
void varena_reset (VArena_R arena);
|
||||
Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size, Opts_varena*R_ opts);
|
||||
Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size);
|
||||
finline AllocatorSP varena_save (VArena_R arena);
|
||||
|
||||
void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
||||
@@ -1159,21 +1159,21 @@ inline
|
||||
Slice_Mem varena__grow(VArena_R vm, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 no_zero) {
|
||||
Slice_Mem result;
|
||||
U8 grow_amount = requested_size - old_allocation.len;
|
||||
if (grow_amount == 0) { result = old_allocation; return; } // Growing when not the last allocation not allowed
|
||||
if (grow_amount == 0) { result = old_allocation; return result; } // Growing when not the last allocation not allowed
|
||||
U8 current_offset = vm->reserve_start + vm->commit_used; assert(old_allocation.ptr == current_offset);
|
||||
Slice_Mem allocation = varena_push_mem(vm, grow_amount, alignment); assert(allocation.ptr != 0);
|
||||
result = (Slice_Mem){ old_allocation.ptr, requested_size + allocation.len }; memory_zero(result.ptr, result.len * no_zero);
|
||||
result = (Slice_Mem){ old_allocation.ptr, requested_size + allocation.len };
|
||||
memory_zero(result.ptr, result.len * no_zero);
|
||||
return result;
|
||||
}
|
||||
finline void varena_release(VArena_R arena) { os_vmem_release(u8_(arena), arena->reserve); }
|
||||
inline
|
||||
Slice_Mem varena__shrink(VArena_R vm, Slice_Mem old_allocation, U8 requested_size, Opts_varena*R_ opts) {
|
||||
assert(opts != nullptr);
|
||||
Slice_Mem result = {0};
|
||||
U8 shrink_amount = old_allocation.len - requested_size;
|
||||
if (lt_s(shrink_amount, 0)) { result = old_allocation; return result; }
|
||||
Slice_Mem varena__shrink(VArena_R vm, Slice_Mem old_allocation, U8 requested_size) {
|
||||
U8 shrink_amount = old_allocation.len - requested_size;
|
||||
if (lt_s(shrink_amount, 0)) { return old_allocation; }
|
||||
U8 current_offset = vm->reserve_start + vm->commit_used; assert(old_allocation.ptr == current_offset);
|
||||
vm->commit_used -= shrink_amount;
|
||||
result = (Slice_Mem){ old_allocation.ptr, requested_size }; return result;
|
||||
return (Slice_Mem){ old_allocation.ptr, requested_size };
|
||||
}
|
||||
finline
|
||||
void varena_rewind(VArena_R vm, AllocatorSP sp) {
|
||||
@@ -1197,32 +1197,11 @@ void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
||||
case AllocatorOp_Reset: vm->commit_used = 0; break;
|
||||
|
||||
case AllocatorOp_Grow_NoZero:
|
||||
case AllocatorOp_Grow: {
|
||||
U8 grow_amount = in.requested_size - in.old_allocation.len;
|
||||
if (grow_amount == 0) {
|
||||
out->allocation = in.old_allocation;
|
||||
return;
|
||||
}
|
||||
U8 current_offset = vm->reserve_start + vm->commit_used;
|
||||
// Growing when not the last allocation not allowed
|
||||
assert(in.old_allocation.ptr == current_offset);
|
||||
Slice_Mem allocation = varena_push_mem(vm, grow_amount, .alignment = in.alignment);
|
||||
assert(allocation.ptr != 0);
|
||||
out->allocation = (Slice_Mem){ in.old_allocation.ptr, in.requested_size + allocation.len };
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * (in.op - AllocatorOp_Grow_NoZero));
|
||||
}
|
||||
case AllocatorOp_Grow:
|
||||
out->allocation = varena__grow(vm, in.old_allocation, in.requested_size, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
case AllocatorOp_Shrink: {
|
||||
U8 current_offset = vm->reserve_start + vm->commit_used;
|
||||
U8 shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
if (lt_s(shrink_amount, 0)) {
|
||||
out->allocation = in.old_allocation;
|
||||
return;
|
||||
}
|
||||
assert(in.old_allocation.ptr == current_offset);
|
||||
vm->commit_used -= shrink_amount;
|
||||
out->allocation = (Slice_Mem){ in.old_allocation.ptr, in.requested_size };
|
||||
}
|
||||
case AllocatorOp_Shrink:
|
||||
out->allocation = varena__shrink(vm, in.old_allocation, in.requested_size);
|
||||
break;
|
||||
|
||||
case AllocatorOp_Rewind: vm->commit_used = in.save_point.slot; break;
|
||||
@@ -1327,80 +1306,80 @@ void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
||||
assert(arena != nullptr);
|
||||
switch (in.op)
|
||||
{
|
||||
case AllocatorOp_Alloc:
|
||||
case AllocatorOp_Alloc_NoZero:
|
||||
out->allocation = arena_push_mem(arena, in.requested_size, .alignment = in.alignment);
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * in.op);
|
||||
break;
|
||||
case AllocatorOp_Alloc:
|
||||
case AllocatorOp_Alloc_NoZero:
|
||||
out->allocation = arena_push_mem(arena, in.requested_size, .alignment = in.alignment);
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * in.op);
|
||||
break;
|
||||
|
||||
case AllocatorOp_Free: break;
|
||||
case AllocatorOp_Reset: arena_reset(arena); break;
|
||||
case AllocatorOp_Free: break;
|
||||
case AllocatorOp_Reset: arena_reset(arena); break;
|
||||
|
||||
case AllocatorOp_Grow:
|
||||
case AllocatorOp_Grow_NoZero: {
|
||||
Arena_R active = arena->current;
|
||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
U8 arena_end = u8_(active) + active->pos;
|
||||
if (alloc_end == arena_end)
|
||||
case AllocatorOp_Grow:
|
||||
case AllocatorOp_Grow_NoZero: {
|
||||
Arena_R active = arena->current;
|
||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
U8 arena_end = u8_(active) + active->pos;
|
||||
if (alloc_end == arena_end)
|
||||
{
|
||||
U8 grow_amount = in.requested_size - in.old_allocation.len;
|
||||
U8 aligned_grow = align_pow2(grow_amount, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
if (active->pos + aligned_grow <= active->backing->reserve)
|
||||
{
|
||||
U8 grow_amount = in.requested_size - in.old_allocation.len;
|
||||
U8 aligned_grow = align_pow2(grow_amount, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
if (active->pos + aligned_grow <= active->backing->reserve)
|
||||
Slice_Mem vresult = varena_push_mem(active->backing, aligned_grow, .alignment = in.alignment);
|
||||
if (vresult.ptr != null)
|
||||
{
|
||||
Slice_Mem vresult = varena_push_mem(active->backing, aligned_grow, .alignment = in.alignment);
|
||||
if (vresult.ptr != null)
|
||||
{
|
||||
active->pos += aligned_grow;
|
||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
||||
memory_zero(in.old_allocation.ptr + in.old_allocation.len, grow_amount * in.op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
}
|
||||
active->pos += aligned_grow;
|
||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
||||
memory_zero(in.old_allocation.ptr + in.old_allocation.len, grow_amount * in.op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Slice_Mem new_alloc = arena__push(arena, in.requested_size, 1, &(Opts_arena){.alignment = in.alignment});
|
||||
if (new_alloc.ptr == null) {
|
||||
out->allocation = (Slice_Mem){0};
|
||||
break;
|
||||
}
|
||||
memory_copy(new_alloc.ptr, in.old_allocation.ptr, in.old_allocation.len);
|
||||
memory_zero(new_alloc.ptr + in.old_allocation.len, (in.requested_size - in.old_allocation.len) * in.op - AllocatorOp_Grow_NoZero);
|
||||
out->allocation = new_alloc;
|
||||
}
|
||||
break;
|
||||
Slice_Mem new_alloc = arena__push(arena, in.requested_size, 1, &(Opts_arena){.alignment = in.alignment});
|
||||
if (new_alloc.ptr == null) {
|
||||
out->allocation = (Slice_Mem){0};
|
||||
break;
|
||||
}
|
||||
memory_copy(new_alloc.ptr, in.old_allocation.ptr, in.old_allocation.len);
|
||||
memory_zero(new_alloc.ptr + in.old_allocation.len, (in.requested_size - in.old_allocation.len) * in.op - AllocatorOp_Grow_NoZero);
|
||||
out->allocation = new_alloc;
|
||||
}
|
||||
break;
|
||||
|
||||
case AllocatorOp_Shrink: {
|
||||
Arena_R active = arena->current;
|
||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
U8 arena_end = u8_(active) + active->pos;
|
||||
if (alloc_end != arena_end) {
|
||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
||||
break;
|
||||
}
|
||||
//SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
U8 aligned_original = align_pow2(in.old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
||||
U8 aligned_new = align_pow2(in.requested_size, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
U8 pos_reduction = aligned_original - aligned_new;
|
||||
active->pos -= pos_reduction;
|
||||
varena__shrink(active->backing, in.old_allocation, in.requested_size, &(Opts_varena){.alignment = in.alignment});
|
||||
case AllocatorOp_Shrink: {
|
||||
Arena_R active = arena->current;
|
||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
U8 arena_end = u8_(active) + active->pos;
|
||||
if (alloc_end != arena_end) {
|
||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
U8 aligned_original = align_pow2(in.old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
||||
U8 aligned_new = align_pow2(in.requested_size, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
U8 pos_reduction = aligned_original - aligned_new;
|
||||
active->pos -= pos_reduction;
|
||||
varena__shrink(active->backing, in.old_allocation, in.requested_size, &(Opts_varena){.alignment = in.alignment});
|
||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
||||
}
|
||||
break;
|
||||
|
||||
case AllocatorOp_Rewind: arena_rewind(arena, in.save_point); break;
|
||||
case AllocatorOp_SavePoint: out->save_point = arena_save(arena); break;
|
||||
case AllocatorOp_Rewind: arena_rewind(arena, in.save_point); break;
|
||||
case AllocatorOp_SavePoint: out->save_point = arena_save(arena); break;
|
||||
|
||||
case AllocatorOp_Query:
|
||||
out->features =
|
||||
AllocatorQuery_Alloc
|
||||
| AllocatorQuery_Resize
|
||||
| AllocatorQuery_Reset
|
||||
| AllocatorQuery_Rewind
|
||||
;
|
||||
out->max_alloc = arena->backing->reserve;
|
||||
out->min_alloc = kilo(4);
|
||||
out->left = out->max_alloc - arena->backing->commit_used;
|
||||
out->save_point = arena_save(arena);
|
||||
break;
|
||||
case AllocatorOp_Query:
|
||||
out->features =
|
||||
AllocatorQuery_Alloc
|
||||
| AllocatorQuery_Resize
|
||||
| AllocatorQuery_Reset
|
||||
| AllocatorQuery_Rewind
|
||||
;
|
||||
out->max_alloc = arena->backing->reserve;
|
||||
out->min_alloc = kilo(4);
|
||||
out->left = out->max_alloc - arena->backing->commit_used;
|
||||
out->save_point = arena_save(arena);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma endregion Arena
|
||||
|
||||
193
C/watl.v0.msvc.c
193
C/watl.v0.msvc.c
@@ -58,10 +58,11 @@ enum { false = 0, true = 1, true_overflow, };
|
||||
#define offset_of(type, member) cast(SSIZE, & (((type*) 0)->member))
|
||||
#define size_of(data) cast(SSIZE, sizeof(data))
|
||||
|
||||
#define R_ __restrict
|
||||
#define V_ volatile
|
||||
#define r_(ptr) cast(typeof_ptr(ptr)*R_, ptr)
|
||||
#define v_(ptr) cast(typeof_ptr(ptr)*V_, ptr)
|
||||
// Not using this since its lottes related.
|
||||
// #define R_ __restrict
|
||||
// #define V_ volatile
|
||||
// #define r_(ptr) cast(typeof_ptr(ptr)*R_, ptr)
|
||||
// #define v_(ptr) cast(typeof_ptr(ptr)*V_, ptr)
|
||||
#define ssize(value) cast(SSIZE, value)
|
||||
|
||||
#define kilo(n) (cast(SSIZE, n) << 10)
|
||||
@@ -369,7 +370,7 @@ Slice_Byte varena__push (VArena* arena, SSIZE amount, SSIZE type_width, Opts_v
|
||||
void varena_release(VArena* arena);
|
||||
void varena_rewind (VArena* arena, AllocatorSP save_point);
|
||||
void varena_reset (VArena* arena);
|
||||
Slice_Byte varena__shrink(VArena* arena, Slice_Byte old_allocation, SSIZE requested_size, Opts_varena* opts);
|
||||
Slice_Byte varena__shrink(VArena* arena, Slice_Byte old_allocation, SSIZE requested_size);
|
||||
AllocatorSP varena_save (VArena* arena);
|
||||
|
||||
void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out);
|
||||
@@ -842,6 +843,44 @@ Slice_Byte farena__push(FArena* arena, SSIZE amount, SSIZE type_width, Opts_fare
|
||||
arena->used += to_commit;
|
||||
return (Slice_Byte){ptr, desired};
|
||||
}
|
||||
inline
|
||||
Slice_Byte farena__grow(FArena* arena, SSIZE requested_size, Slice_Byte old_allocation, SSIZE alignment, B32 no_zero) {
|
||||
// Check if the allocation is at the end of the arena
|
||||
Byte* alloc_end = old_allocation.ptr + old_allocation.len;
|
||||
Byte* arena_end = cast(Byte*, cast(SSIZE, arena->start) + arena->used);
|
||||
if (alloc_end != arena_end) {
|
||||
// Not at the end, can't grow in place
|
||||
return (Slice_Byte){0};
|
||||
}
|
||||
// Calculate growth
|
||||
SSIZE grow_amount = requested_size - old_allocation.len;
|
||||
SSIZE aligned_grow = align_pow2(grow_amount, alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
SSIZE unused = arena->capacity - arena->used;
|
||||
if (aligned_grow > unused) {
|
||||
// Not enough space
|
||||
return (Slice_Byte){0};
|
||||
}
|
||||
arena->used += aligned_grow;
|
||||
Slice_Byte result = (Slice_Byte){old_allocation.ptr, requested_size};
|
||||
memory_zero(old_allocation.ptr + old_allocation.len, grow_amount * cast(SSIZE, no_zero));
|
||||
return result;
|
||||
}
|
||||
inline
|
||||
Slice_Byte farena__shrink(FArena* arena, Slice_Byte old_allocation, SSIZE requested_size, SSIZE alignment) {
|
||||
// Check if the allocation is at the end of the arena
|
||||
Byte* alloc_end = old_allocation.ptr + old_allocation.len;
|
||||
Byte* arena_end = cast(Byte*, cast(SSIZE, arena->start) + arena->used);
|
||||
if (alloc_end != arena_end) {
|
||||
// Not at the end, can't shrink but return adjusted size
|
||||
return (Slice_Byte){old_allocation.ptr, requested_size};
|
||||
}
|
||||
// Calculate shrinkage
|
||||
//SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
SSIZE aligned_original = align_pow2(old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
||||
SSIZE aligned_new = align_pow2(requested_size, alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
arena->used -= (aligned_original - aligned_new);
|
||||
return (Slice_Byte){old_allocation.ptr, requested_size};
|
||||
}
|
||||
inline void farena_reset(FArena* arena) { arena->used = 0; }
|
||||
inline
|
||||
void farena_rewind(FArena* arena, AllocatorSP save_point) {
|
||||
@@ -867,61 +906,19 @@ void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * cast(SSIZE, in.op));
|
||||
break;
|
||||
|
||||
case AllocatorOp_Free:
|
||||
break;
|
||||
case AllocatorOp_Reset:
|
||||
farena_reset(arena);
|
||||
break;
|
||||
case AllocatorOp_Free: break;
|
||||
case AllocatorOp_Reset: farena_reset(arena); break;
|
||||
|
||||
case AllocatorOp_Grow:
|
||||
case AllocatorOp_Grow_NoZero: {
|
||||
// Check if the allocation is at the end of the arena
|
||||
Byte* alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
Byte* arena_end = cast(Byte*, cast(SSIZE, arena->start) + arena->used);
|
||||
if (alloc_end != arena_end) {
|
||||
// Not at the end, can't grow in place
|
||||
out->allocation = (Slice_Byte){0};
|
||||
break;
|
||||
}
|
||||
// Calculate growth
|
||||
SSIZE grow_amount = in.requested_size - in.old_allocation.len;
|
||||
SSIZE aligned_grow = align_pow2(grow_amount, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
SSIZE unused = arena->capacity - arena->used;
|
||||
if (aligned_grow > unused) {
|
||||
// Not enough space
|
||||
out->allocation = (Slice_Byte){0};
|
||||
break;
|
||||
}
|
||||
arena->used += aligned_grow;
|
||||
out->allocation = (Slice_Byte){in.old_allocation.ptr, in.requested_size};
|
||||
memory_zero(in.old_allocation.ptr + in.old_allocation.len, grow_amount * cast(SSIZE, in.op - AllocatorOp_Grow_NoZero));
|
||||
}
|
||||
case AllocatorOp_Grow_NoZero:
|
||||
out->allocation = farena__grow(arena, in.requested_size, in.old_allocation, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
case AllocatorOp_Shrink:
|
||||
out->allocation = farena__shrink(arena, in.old_allocation, in.requested_size, in.alignment);
|
||||
break;
|
||||
|
||||
case AllocatorOp_Shrink: {
|
||||
// Check if the allocation is at the end of the arena
|
||||
Byte* alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
||||
Byte* arena_end = cast(Byte*, cast(SSIZE, arena->start) + arena->used);
|
||||
if (alloc_end != arena_end) {
|
||||
// Not at the end, can't shrink but return adjusted size
|
||||
out->allocation = (Slice_Byte){in.old_allocation.ptr, in.requested_size};
|
||||
break;
|
||||
}
|
||||
// Calculate shrinkage
|
||||
//SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
SSIZE aligned_original = align_pow2(in.old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
||||
SSIZE aligned_new = align_pow2(in.requested_size, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
arena->used -= (aligned_original - aligned_new);
|
||||
out->allocation = (Slice_Byte){in.old_allocation.ptr, in.requested_size};
|
||||
}
|
||||
break;
|
||||
|
||||
case AllocatorOp_Rewind:
|
||||
farena_rewind(arena, in.save_point);
|
||||
break;
|
||||
case AllocatorOp_SavePoint:
|
||||
out->save_point = farena_save(* arena);
|
||||
break;
|
||||
case AllocatorOp_Rewind: farena_rewind(arena, in.save_point); break;
|
||||
case AllocatorOp_SavePoint: out->save_point = farena_save(* arena); break;
|
||||
|
||||
case AllocatorOp_Query:
|
||||
out->features =
|
||||
@@ -1044,7 +1041,7 @@ inline void os_vmem_release(void* vm, SSIZE size) { VirtualFree(vm, 0, MS_MEM_R
|
||||
#pragma endregion OS
|
||||
|
||||
#pragma region VArena (Virutal Address Space Arena)
|
||||
finline U8 varena_header_size(void) { return align_pow2(size_of(VArena), MEMORY_ALIGNMENT_DEFAULT); }
|
||||
finline SSIZE varena_header_size(void) { return align_pow2(size_of(VArena), MEMORY_ALIGNMENT_DEFAULT); }
|
||||
inline
|
||||
VArena* varena__make(Opts_varena_make* opts) {
|
||||
assert(opts != nullptr);
|
||||
@@ -1094,21 +1091,26 @@ Slice_Byte varena__push(VArena* vm, SSIZE amount, SSIZE type_width, Opts_varena*
|
||||
vm->commit_used = to_be_used;
|
||||
return (Slice_Byte){.ptr = cast(Byte*, current_offset), .len = requested_size};
|
||||
}
|
||||
inline void varena_release(VArena* arena) { os_vmem_release(arena, arena->reserve); }
|
||||
inline Slice_Byte varena__shrink(VArena* vm, Slice_Byte old_allocation, SSIZE requested_size, Opts_varena* opts) {
|
||||
assert(opts != nullptr);
|
||||
Slice_Byte result = {0};
|
||||
SSIZE current_offset = vm->reserve_start + vm->commit_used;
|
||||
SSIZE shrink_amount = old_allocation.len - requested_size;
|
||||
if (shrink_amount < 0) {
|
||||
result = old_allocation;
|
||||
return result;
|
||||
}
|
||||
assert(old_allocation.ptr == cast(Byte*, current_offset));
|
||||
vm->commit_used -= shrink_amount;
|
||||
result = (Slice_Byte){ old_allocation.ptr, requested_size };
|
||||
inline
|
||||
Slice_Byte varena__grow(VArena* vm, SSIZE requested_size, Slice_Byte old_allocation, SSIZE alignment, B32 no_zero) {
|
||||
assert(vm != nullptr);
|
||||
SSIZE grow_amount = requested_size - old_allocation.len;
|
||||
if (grow_amount == 0) { return old_allocation; } // Growing when not the last allocation not allowed
|
||||
SSIZE current_offset = vm->reserve_start + vm->commit_used; assert(old_allocation.ptr == cast(Byte*, current_offset));
|
||||
Slice_Byte allocation = varena_push_array(vm, Byte, grow_amount, alignment); assert(allocation.ptr != nullptr);
|
||||
Slice_Byte result = (Slice_Byte){ old_allocation.ptr, requested_size };
|
||||
memory_zero(allocation.ptr, allocation.len * no_zero);
|
||||
return result;
|
||||
}
|
||||
inline Slice_Byte varena__shrink(VArena* vm, Slice_Byte old_allocation, SSIZE requested_size) {
|
||||
SSIZE current_offset = vm->reserve_start + vm->commit_used;
|
||||
SSIZE shrink_amount = old_allocation.len - requested_size;
|
||||
if (shrink_amount < 0) { return old_allocation; }
|
||||
assert(old_allocation.ptr == cast(Byte*, current_offset));
|
||||
vm->commit_used -= shrink_amount;
|
||||
return (Slice_Byte){ old_allocation.ptr, requested_size };
|
||||
}
|
||||
inline void varena_release(VArena* arena) { os_vmem_release(arena, arena->reserve); }
|
||||
inline
|
||||
void varena_rewind(VArena* vm, AllocatorSP sp) {
|
||||
assert(vm != nullptr);
|
||||
@@ -1127,47 +1129,19 @@ void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * cast(SSIZE, in.op));
|
||||
break;
|
||||
|
||||
case AllocatorOp_Free:
|
||||
case AllocatorOp_Free: break;
|
||||
case AllocatorOp_Reset: vm->commit_used = 0; break;
|
||||
|
||||
case AllocatorOp_Grow_NoZero:
|
||||
case AllocatorOp_Grow:
|
||||
out->allocation = varena__grow(vm, in.requested_size, in.old_allocation, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
||||
break;
|
||||
case AllocatorOp_Reset:
|
||||
vm->commit_used = 0;
|
||||
case AllocatorOp_Shrink:
|
||||
out->allocation = varena__shrink(vm, in.old_allocation, in.requested_size);
|
||||
break;
|
||||
|
||||
case AllocatorOp_Grow_NoZero:
|
||||
case AllocatorOp_Grow: {
|
||||
SSIZE grow_amount = in.requested_size - in.old_allocation.len;
|
||||
if (grow_amount == 0) {
|
||||
out->allocation = in.old_allocation;
|
||||
return;
|
||||
}
|
||||
SSIZE current_offset = vm->reserve_start + vm->commit_used;
|
||||
// Growing when not the last allocation not allowed
|
||||
assert(in.old_allocation.ptr == cast(Byte*, current_offset));
|
||||
Slice_Byte allocation = varena_push_array(vm, Byte, grow_amount, .alignment = in.alignment);
|
||||
assert(allocation.ptr != nullptr);
|
||||
out->allocation = (Slice_Byte){ in.old_allocation.ptr, in.requested_size };
|
||||
memory_zero(out->allocation.ptr, out->allocation.len * (in.op - AllocatorOp_Grow_NoZero));
|
||||
}
|
||||
break;
|
||||
case AllocatorOp_Shrink: {
|
||||
SSIZE current_offset = vm->reserve_start + vm->commit_used;
|
||||
SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
||||
if (shrink_amount < 0) {
|
||||
out->allocation = in.old_allocation;
|
||||
return;
|
||||
}
|
||||
assert(in.old_allocation.ptr == cast(Byte*, current_offset));
|
||||
vm->commit_used -= shrink_amount;
|
||||
out->allocation = (Slice_Byte){ in.old_allocation.ptr, in.requested_size };
|
||||
}
|
||||
break;
|
||||
|
||||
case AllocatorOp_Rewind:
|
||||
vm->commit_used = in.save_point.slot;
|
||||
break;
|
||||
case AllocatorOp_SavePoint:
|
||||
out->save_point = varena_save(vm);
|
||||
break;
|
||||
case AllocatorOp_Rewind: vm->commit_used = in.save_point.slot; break;
|
||||
case AllocatorOp_SavePoint: out->save_point = varena_save(vm); break;
|
||||
|
||||
case AllocatorOp_Query:
|
||||
out->features =
|
||||
@@ -1321,8 +1295,7 @@ void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
||||
SSIZE aligned_new = align_pow2(in.requested_size, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||
SSIZE pos_reduction = aligned_original - aligned_new;
|
||||
active->pos -= pos_reduction;
|
||||
varena__shrink(active->backing, in.old_allocation, in.requested_size, &(Opts_varena){.alignment = in.alignment});
|
||||
out->allocation = (Slice_Byte){in.old_allocation.ptr, in.requested_size};
|
||||
out->allocation = varena__shrink(active->backing, in.old_allocation, in.requested_size);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user