-
-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support allocator instances, introduce string builder and more changes
* Allocators now can have instances * Rename stringbuffer to stringbuilder and add more useful methods to it * Move string format function to stringbuilder * Add stringview.sub method * Rename generic_allocator to general_allocator * Add the FixedLinearAllocator to perform efficient allocations when not using the GC, more useful allocators will come later
- Loading branch information
Showing
25 changed files
with
735 additions
and
433 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
## if not pragmas.nogc then | ||
require 'allocators.gc' | ||
global default_allocator = @gc_allocator | ||
global default_allocator: auto = &gc_allocator | ||
global DefaultAllocator: auto = GCAllocator | ||
## else | ||
require 'allocators.generic' | ||
global default_allocator = @generic_allocator | ||
require 'allocators.general' | ||
global default_allocator: auto = &general_allocator | ||
global DefaultAllocator: auto = GeneralAllocator | ||
## end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
-- Fixed Linear Allocator | ||
-- | ||
-- This allocator allocates everything in a contiguous fixed array. | ||
-- The memory will reside on the stack if declared inside a function | ||
-- or on the static memory storage if declared in a top scope. | ||
-- Reallocations and deallocations does not free space unless for the most recent allocation. | ||
-- To free space `dealloc_all` should be called once all operations on its allocations are finished. | ||
-- | ||
-- The purpose of this allocator is to have many quick allocations with almost | ||
-- no runtime cost when the maximum used space is known ahead. | ||
-- Also useful to deallocate many small allocated objects at once. | ||
-- Also useful for temporary allocations. | ||
-- | ||
-- When declaring it on the stack if the allocator is not reused then there is no need to perform | ||
-- deallocations, just leave the scope ends to have a quick cleanup. | ||
-- | ||
-- Take care to not use a large space when using it on the stack, or the program may crash | ||
-- with not enough stack space. | ||
-- | ||
-- By default allocations are aligned to 8 bytes unless explicit told otherwise. | ||
-- By default allocations are filled with zeros even for normal alloc/realloc functions. | ||
-- When there is not enough space nilptr is returned on allocations. | ||
|
||
require 'memory' | ||
require 'allocators.interface' | ||
|
||
local function align_addr(addr: usize, align: usize): usize <inline> | ||
return (addr + (align-1)) & ~(align-1) | ||
end | ||
|
||
## local make_fixed_linear_allocator = generalize(function(N, align) | ||
## align = align or 8 | ||
## staticassert(N % align == 0, 'FixedLinearAllocator: N must be multiple of align') | ||
local ALIGN <comptime> = #[align]# | ||
local N <comptime> = #[N]# | ||
local FixedLinearAllocatorN <aligned(#[align]#)> = @record{ | ||
memory: byte[N], | ||
last_pos: usize, | ||
next_pos: usize | ||
} | ||
|
||
function FixedLinearAllocatorN:alloc(size: usize): pointer | ||
local pos: usize = self.next_pos | ||
local advanced_pos: usize = pos + size | ||
if unlikely(advanced_pos > N) then return nilptr end | ||
local p: pointer = &self.memory[pos] | ||
self.last_pos = pos | ||
self.next_pos = align_addr(advanced_pos, ALIGN) | ||
return p | ||
end | ||
|
||
function FixedLinearAllocatorN:alloc0(size: usize): pointer <inline> | ||
-- the allocator memory should already by pre initialized to zeros | ||
return self:alloc(size) | ||
end | ||
|
||
function FixedLinearAllocatorN:realloc(p: pointer, size: usize): pointer | ||
local pos: usize = (@usize)(p) - (@usize)(&self.memory[0]) | ||
if pos == self.last_pos then -- grow last allocation | ||
local advanced_pos: usize = pos + size | ||
if unlikely(advanced_pos > N) then return nilptr end | ||
local old_next_pos: usize = self.next_pos | ||
if likely(size > 0) then | ||
self.next_pos = align_addr(advanced_pos, ALIGN) | ||
else | ||
self.next_pos = pos | ||
end | ||
-- fill with zeros the removed part in case of shrink | ||
if unlikely(self.next_pos < old_next_pos) then | ||
memory.zero(&self.memory[self.next_pos], old_next_pos - self.next_pos) | ||
end | ||
return p | ||
else | ||
if unlikely(size == 0) then return nilptr end | ||
-- move to a new allocation | ||
local newp: pointer = self:alloc(size) | ||
if unlikely(newp == nilptr) then return nilptr end | ||
return newp | ||
end | ||
end | ||
|
||
function FixedLinearAllocatorN:realloc0(p: pointer, newsize: usize, oldsize: usize): pointer <inline> | ||
-- the allocator memory should already by pre initialized to zeros | ||
return self:realloc(p, newsize) | ||
end | ||
|
||
function FixedLinearAllocatorN:dealloc(p: pointer) | ||
local pos: usize = (@usize)(p) - (@usize)(&self.memory[0]) | ||
if pos == self.last_pos then -- shrink last allocation | ||
memory.zero(&self.memory[pos], self.next_pos - pos) | ||
self.next_pos = pos | ||
end | ||
end | ||
|
||
-- Free all allocations, effectively resetting the allocator to the zeroed state. | ||
function FixedLinearAllocatorN:dealloc_all() | ||
memory.zero(&self.memory[0], #self.memory) | ||
self.last_pos = 0 | ||
self.next_pos = 0 | ||
end | ||
|
||
## implement_allocator_interface(FixedLinearAllocatorN) | ||
|
||
## return FixedLinearAllocatorN | ||
## end) | ||
|
||
global FixedLinearAllocator: type = #[make_fixed_linear_allocator]# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.