remove limitations from PagingArena, small improvements
This commit is contained in:
parent
a2ad1f9364
commit
8bc49b5b67
3 changed files with 135 additions and 76 deletions
|
|
@ -26,11 +26,13 @@ ArenaEvent :: enum {
|
||||||
|
|
||||||
Save;
|
Save;
|
||||||
Restore;
|
Restore;
|
||||||
|
|
||||||
|
Report;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ArenaPush pushes a value of type T to the current context.arena.
|
/// ArenaPush pushes a value of type T to the current context.arena.
|
||||||
ArenaPush :: ($T: Type, loc := #caller_location) -> *T {
|
ArenaPush :: ($T: Type, loc := #caller_location) -> *T {
|
||||||
return ArenaPushSize(size_of(T), loc = loc).(*T);
|
return ArenaPushSize(size_of(T), align_of(T), loc = loc).(*T);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ArenaPushSize pushes size bytes to the current context.arena.
|
/// ArenaPushSize pushes size bytes to the current context.arena.
|
||||||
|
|
@ -72,6 +74,11 @@ ArenaRelease :: (loc := #caller_location) {
|
||||||
context.arena.proc(.Teardown, context.arena.data, 0, 0, 0, null, null, loc);
|
context.arena.proc(.Teardown, context.arena.data, 0, 0, 0, null, null, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArenaReport :: (loc := #caller_location) {
|
||||||
|
TrySetupArena(*context.arena, loc);
|
||||||
|
context.arena.proc(.Report, context.arena.data, 0, 0, 0, null, null, loc);
|
||||||
|
}
|
||||||
|
|
||||||
/// ArenaToAllocator wraps the given arena, allowing it to be used with Jai's builtin Allocator system.
|
/// ArenaToAllocator wraps the given arena, allowing it to be used with Jai's builtin Allocator system.
|
||||||
ArenaToAllocator :: (arena: *Arena) -> Allocator {
|
ArenaToAllocator :: (arena: *Arena) -> Allocator {
|
||||||
return .{ proc = JaiAllocatorProc, data = arena };
|
return .{ proc = JaiAllocatorProc, data = arena };
|
||||||
|
|
@ -87,6 +94,7 @@ BumpData :: struct {
|
||||||
offset: int;
|
offset: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// BumpArena is a simple linear Arena.
|
||||||
BumpArena :: (bump: *BumpData) -> Arena {
|
BumpArena :: (bump: *BumpData) -> Arena {
|
||||||
return .{ proc = BumpArenaProc, data = bump };
|
return .{ proc = BumpArenaProc, data = bump };
|
||||||
}
|
}
|
||||||
|
|
@ -171,6 +179,18 @@ BumpArenaProc :: (
|
||||||
if wm < 0 || wm >= bump.memory.count
|
if wm < 0 || wm >= bump.memory.count
|
||||||
{ Panic("jc: BumpArena, restored invalid savepoint", loc = caller); }
|
{ Panic("jc: BumpArena, restored invalid savepoint", loc = caller); }
|
||||||
bump.offset = wm;
|
bump.offset = wm;
|
||||||
|
|
||||||
|
case .Report;
|
||||||
|
WriteString("\n--- BumpArena Report ---");
|
||||||
|
|
||||||
|
WriteString("\nMem Max: ");
|
||||||
|
WriteNumber(bump.memory.count);
|
||||||
|
|
||||||
|
WriteString("\nMem Used: ");
|
||||||
|
WriteNumber(bump.offset);
|
||||||
|
|
||||||
|
WriteString("\n--- BumpArena Report ---\n\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -185,60 +205,62 @@ PagingArenaProc :: (
|
||||||
|
|
||||||
caller: Source_Code_Location
|
caller: Source_Code_Location
|
||||||
) -> *void {
|
) -> *void {
|
||||||
MaxPages :: 64;
|
|
||||||
|
|
||||||
PageArenaData :: struct {
|
|
||||||
pages: [MaxPages]Page;
|
|
||||||
count: int;
|
|
||||||
in_use: int;
|
|
||||||
|
|
||||||
Page :: struct {
|
Page :: struct {
|
||||||
base: *u8;
|
base: *u8;
|
||||||
|
next: *Page;
|
||||||
offset: int;
|
offset: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageArenaData :: struct {
|
||||||
|
pages: *Page;
|
||||||
|
current: *Page;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note(judah): page 0 has a special offset because it stores the header
|
PageNOffset :: size_of(Page);
|
||||||
Page0Offset :: #run AlignForward(size_of(PageArenaData), align_of(PageArenaData));
|
Page0Offset :: size_of(PageArenaData) + PageNOffset;
|
||||||
|
|
||||||
|
NewPage :: inline (previous_base: *void) -> *Page {
|
||||||
|
mem := MemAcquirePage(.CommitImmediately);
|
||||||
|
|
||||||
|
p := mem.(*Page);
|
||||||
|
p.base = mem;
|
||||||
|
p.next = null;
|
||||||
|
p.offset = PageNOffset;
|
||||||
|
|
||||||
NewPage :: inline (previous_base: *void) -> PageArenaData.Page {
|
|
||||||
p: PageArenaData.Page = ---;
|
|
||||||
p.base = MemAcquirePage(.CommitImmediately);
|
|
||||||
p.offset = 0;
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
data := arena_data.(*PageArenaData);
|
data := arena_data.(*PageArenaData);
|
||||||
if event == {
|
if event == {
|
||||||
case .Setup;
|
case .Setup;
|
||||||
page := NewPage(null);
|
// This is a special page that stores both the PageArenaData and Page 0
|
||||||
data = page.base.(*PageArenaData);
|
mem := MemAcquirePage(.CommitImmediately);
|
||||||
|
header := mem.(*PageArenaData);
|
||||||
|
|
||||||
|
page := (mem + size_of(PageArenaData)).(*Page);
|
||||||
|
page.base = mem;
|
||||||
|
page.next = null;
|
||||||
page.offset = Page0Offset;
|
page.offset = Page0Offset;
|
||||||
data.pages[0] = page;
|
|
||||||
|
|
||||||
data.in_use = 1;
|
header.pages = page;
|
||||||
data.count = 1;
|
header.current = page;
|
||||||
|
|
||||||
return data;
|
return header;
|
||||||
|
|
||||||
case .Teardown;
|
case .Teardown;
|
||||||
// @note(judah): release in reverse oreder so we don't release the memory
|
page := data.pages;
|
||||||
// containing the header until we don't need it anymore.
|
while page != null {
|
||||||
i := data.count - 1;
|
next := page.next;
|
||||||
while i >= 0 {
|
MemReleasePage(page.base, PageSize);
|
||||||
page := data.pages[i];
|
page = next;
|
||||||
if page.base != null
|
|
||||||
{ MemReleasePage(page.base, PageSize); }
|
|
||||||
|
|
||||||
i -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case .Acquire;
|
case .Acquire;
|
||||||
Assert(data.count != 0, "jc: PageArena, no pages exist");
|
Assert(data.pages != null, "jc: PageArena, no pages exist");
|
||||||
|
Assert(data.current != null, "jc: PageArena, no current page");
|
||||||
|
|
||||||
last := *data.pages[data.in_use - 1];
|
cur := data.current;
|
||||||
end := last.base + last.offset;
|
end := cur.base + cur.offset;
|
||||||
if new_size == 0
|
if new_size == 0
|
||||||
{ return end; }
|
{ return end; }
|
||||||
|
|
||||||
|
|
@ -246,65 +268,87 @@ PagingArenaProc :: (
|
||||||
size := new_size + (ptr - end);
|
size := new_size + (ptr - end);
|
||||||
|
|
||||||
// create or reuse page
|
// create or reuse page
|
||||||
if last.offset + size > PageSize {
|
if cur.offset + size > PageSize {
|
||||||
if data.in_use >= MaxPages
|
page: *Page;
|
||||||
{ Panic("jc: PageArena, max page count"); }
|
if cur.next != null {
|
||||||
|
page = cur.next;
|
||||||
page: *PageArenaData.Page;
|
|
||||||
if data.in_use < data.count {
|
|
||||||
page = *data.pages[data.in_use];
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p := NewPage(data.pages[data.count - 1].base);
|
cur.next = NewPage(cur.base);
|
||||||
data.pages[data.count] = p;
|
page = cur.next;
|
||||||
page = *data.pages[data.count];
|
|
||||||
|
|
||||||
data.count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.in_use += 1;
|
|
||||||
|
|
||||||
ptr = page.base;
|
ptr = page.base + page.offset;
|
||||||
size = new_size;
|
size = new_size;
|
||||||
last = page;
|
cur = page;
|
||||||
|
|
||||||
|
data.current = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
last.offset += size;
|
cur.offset += size;
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
case .Reset;
|
case .Reset;
|
||||||
for 0..data.count - 1 {
|
page := data.pages;
|
||||||
page := *data.pages[it];
|
|
||||||
|
|
||||||
if it == 0 {
|
|
||||||
page.offset = Page0Offset;
|
page.offset = Page0Offset;
|
||||||
}
|
|
||||||
else {
|
page = page.next;
|
||||||
page.offset = 0;
|
while page != null {
|
||||||
}
|
page.offset = PageNOffset;
|
||||||
|
page = page.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.in_use = 1;
|
data.current = data.pages;
|
||||||
|
|
||||||
case .Save;
|
case .Save;
|
||||||
return data.in_use.(*void);
|
return data.current.(*void);
|
||||||
|
|
||||||
case .Restore;
|
case .Restore;
|
||||||
in_use_at_save := old_ptr.(int);
|
if old_ptr == null
|
||||||
|
{ Panic("jc: PagingArena, restore point was invalid"); }
|
||||||
|
|
||||||
// @note(judah): We need to restore from the savepoint to count
|
// @note(judah): when restoring, we need to reset every page
|
||||||
// because we could've created more pages inbetween save/restore
|
// from the savepoint forward
|
||||||
for in_use_at_save..data.count - 1 {
|
saved_page := old_ptr.(*Page);
|
||||||
p := *data.pages[it];
|
while saved_page != null {
|
||||||
if it == 0 {
|
if saved_page == data.pages {
|
||||||
p.offset = Page0Offset;
|
saved_page.offset = Page0Offset;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.offset = 0;
|
saved_page.offset = PageNOffset;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.in_use = in_use_at_save;
|
saved_page = saved_page.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
case .Report;
|
||||||
|
pages := 0;
|
||||||
|
allocated := 0;
|
||||||
|
in_use := 0;
|
||||||
|
|
||||||
|
page := data.pages;
|
||||||
|
while page != null {
|
||||||
|
pages += 1;
|
||||||
|
allocated += PageSize;
|
||||||
|
in_use += page.offset;
|
||||||
|
|
||||||
|
page = page.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteString("\n--- PagingArena Report ---");
|
||||||
|
WriteString("\nPages: ");
|
||||||
|
WriteNumber(pages);
|
||||||
|
|
||||||
|
WriteString("\nMem Used: ");
|
||||||
|
WriteNumber(in_use);
|
||||||
|
|
||||||
|
WriteString("\nMem Allocated: ");
|
||||||
|
WriteNumber(allocated);
|
||||||
|
WriteString(" (PageSize * N Pages)");
|
||||||
|
|
||||||
|
|
||||||
|
WriteString("\n--- PagingArena Report ---\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -326,10 +370,12 @@ TempArenaProc :: (
|
||||||
malloc :: (size: int) -> *void #c_call #foreign libc;
|
malloc :: (size: int) -> *void #c_call #foreign libc;
|
||||||
free :: (ptr: *void) #c_call #foreign libc;
|
free :: (ptr: *void) #c_call #foreign libc;
|
||||||
|
|
||||||
|
TempMemorySize :: (32 * Kilobyte) + size_of(BumpData);
|
||||||
|
|
||||||
if event == {
|
if event == {
|
||||||
// @note(judah): allows the temp arena to initialize itself without relying on another arena to provide its memory.
|
// @note(judah): allows the temp arena to initialize itself without relying on another arena to provide its memory.
|
||||||
case .Setup;
|
case .Setup;
|
||||||
mcount := AlignForward(size_of(BumpData) + 32768).(int);
|
mcount := AlignForward(TempMemorySize).(int);
|
||||||
memory := malloc(mcount).(*u8);
|
memory := malloc(mcount).(*u8);
|
||||||
MemZero(memory, mcount);
|
MemZero(memory, mcount);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,18 +201,21 @@ DebugBuild :: #run -> bool {
|
||||||
PrintStackTrace :: () {
|
PrintStackTrace :: () {
|
||||||
WriteStderrString("\n----- Stack Trace -----\n");
|
WriteStderrString("\n----- Stack Trace -----\n");
|
||||||
|
|
||||||
node := context.stack_trace.next;
|
node := context.stack_trace;
|
||||||
while node != null {
|
while node != null {
|
||||||
|
if node.info == null
|
||||||
|
{ break; }
|
||||||
|
|
||||||
loc := node.info.location;
|
loc := node.info.location;
|
||||||
loc.line_number = node.line_number;
|
loc.line_number = node.line_number;
|
||||||
WriteStderrLocation(loc);
|
WriteStderrLocation(loc);
|
||||||
|
|
||||||
name := node.info.name;
|
name := node.info.name;
|
||||||
if name.count <= 0
|
if name.count <= 0
|
||||||
{ name = "(unknown)"; }
|
{ name = "#run"; }
|
||||||
|
|
||||||
WriteStderrString(": in ", name, "\n");
|
WriteStderrString(": in ", name, "\n");
|
||||||
|
|
||||||
if node.next != null
|
node = node.next;
|
||||||
{ node = node.next; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
PLAN.Judah
10
PLAN.Judah
|
|
@ -9,6 +9,16 @@ This is what I'm doing day-to-day.
|
||||||
: notes, todos, etc.
|
: notes, todos, etc.
|
||||||
|
|
||||||
|
|
||||||
|
/ 09.09.25
|
||||||
|
|
||||||
|
+ PagingArena needs higher max memory
|
||||||
|
+ added ArenaReport
|
||||||
|
+ fixed PrintStackTrace
|
||||||
|
+ add align_of(T) to ArenaPush
|
||||||
|
|
||||||
|
: should TempArena get more than 32k?
|
||||||
|
|
||||||
|
|
||||||
/ 09.08.25
|
/ 09.08.25
|
||||||
|
|
||||||
+ implemented PagingArena on mac
|
+ implemented PagingArena on mac
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue