mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-02 11:19:31 -04:00
77 lines
2.0 KiB
Odin
77 lines
2.0 KiB
Odin
#+build !js
|
|
#+build !orca
|
|
#+build !wasi
|
|
package runtime
|
|
|
|
import "base:intrinsics"
|
|
|
|
heap_allocator :: proc() -> Allocator {
|
|
return Allocator{
|
|
procedure = heap_allocator_proc,
|
|
data = nil,
|
|
}
|
|
}
|
|
|
|
heap_allocator_proc :: proc(
|
|
allocator_data: rawptr,
|
|
mode: Allocator_Mode,
|
|
size, alignment: int,
|
|
old_memory: rawptr,
|
|
old_size: int,
|
|
loc := #caller_location,
|
|
) -> ([]byte, Allocator_Error) {
|
|
assert(alignment <= ODIN_HEAP_MAX_ALIGNMENT, "Heap allocation alignment beyond ODIN_HEAP_MAX_ALIGNMENT bytes is not supported.", loc = loc)
|
|
assert(alignment >= 0, "Alignment must be greater than or equal to zero.", loc = loc)
|
|
switch mode {
|
|
case .Alloc:
|
|
// All allocations are aligned to at least their size up to
|
|
// `HEAP_MAX_ALIGNMENT`, and by virtue of binary arithmetic, any
|
|
// address aligned to N will also be aligned to N>>1.
|
|
//
|
|
// Therefore, we have no book-keeping costs for alignment.
|
|
ptr := heap_alloc(max(size, alignment))
|
|
if ptr == nil {
|
|
return nil, .Out_Of_Memory
|
|
}
|
|
return transmute([]byte)Raw_Slice{ data = ptr, len = size }, nil
|
|
case .Alloc_Non_Zeroed:
|
|
ptr := heap_alloc(max(size, alignment), zero_memory = false)
|
|
if ptr == nil {
|
|
return nil, .Out_Of_Memory
|
|
}
|
|
return transmute([]byte)Raw_Slice{ data = ptr, len = size }, nil
|
|
case .Resize:
|
|
ptr := heap_resize(old_memory, old_size, max(size, alignment))
|
|
if ptr == nil {
|
|
return nil, .Out_Of_Memory
|
|
}
|
|
return transmute([]byte)Raw_Slice{ data = ptr, len = size }, nil
|
|
case .Resize_Non_Zeroed:
|
|
ptr := heap_resize(old_memory, old_size, max(size, alignment), zero_memory = false)
|
|
if ptr == nil {
|
|
return nil, .Out_Of_Memory
|
|
}
|
|
return transmute([]byte)Raw_Slice{ data = ptr, len = size }, nil
|
|
case .Free:
|
|
heap_free(old_memory)
|
|
case .Free_All:
|
|
return nil, .Mode_Not_Implemented
|
|
case .Query_Features:
|
|
set := (^Allocator_Mode_Set)(old_memory)
|
|
if set != nil {
|
|
set^ = {
|
|
.Alloc,
|
|
.Alloc_Non_Zeroed,
|
|
.Resize,
|
|
.Resize_Non_Zeroed,
|
|
.Free,
|
|
.Query_Features,
|
|
}
|
|
}
|
|
return nil, nil
|
|
case .Query_Info:
|
|
return nil, .Mode_Not_Implemented
|
|
}
|
|
return nil, nil
|
|
}
|