compiler/
kernel/
lib/
scripts/
seed/
sublime/
test/
acceptance/
boot/
bootstrap/
cycles/
dispatch/
loader/
mmio/
native/
packages/
pages/
runtime/
scheduling/
shared/
slots/
smp/
support/
std/
lang/
alloc.rad
3.3 KiB
lang.rad
70 B
std.lib
79 B
std.rad
82 B
sync/
termination/
tests/
trap/
package-golden
1.6 KiB
run
3.1 KiB
runner.rad
10.5 KiB
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
9.2 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
662 B
test/support/std/lang/alloc.rad
raw
| 1 | //! Arena allocation support for binary lowering fixtures. |
| 2 | |
| 3 | /// Error returned when an arena cannot satisfy an allocation. |
| 4 | export union AllocError: Copy { |
| 5 | /// The arena has insufficient storage. |
| 6 | OutOfMemory, |
| 7 | } |
| 8 | |
| 9 | /// Bump allocator backed by a byte slice. |
| 10 | export record Arena { |
| 11 | /// Backing storage. |
| 12 | data: *mut [u8], |
| 13 | /// Current allocation offset in bytes. |
| 14 | offset: u32, |
| 15 | } |
| 16 | |
| 17 | /// Create an arena backed by `data`. |
| 18 | export fn new(data: *mut [u8]) -> Arena { |
| 19 | return Arena { data, offset: 0 }; |
| 20 | } |
| 21 | |
| 22 | /// Reset the arena to its initial empty state. |
| 23 | export fn reset(arena: &mut Arena) { |
| 24 | set arena.offset = 0; |
| 25 | } |
| 26 | |
| 27 | /// Return the number of bytes committed in the arena. |
| 28 | export fn used(arena: &Arena) -> u32 { |
| 29 | return arena.offset; |
| 30 | } |
| 31 | |
| 32 | /// Allocate aligned storage without changing the arena after failure. |
| 33 | export unsafe fn alloc(arena: *unsafe mut Arena, size: u32, alignment: u32) -> *mut opaque throws (AllocError) { |
| 34 | assert alignment > 0; |
| 35 | assert size > 0; |
| 36 | assert (alignment & (alignment - 1)) == 0; |
| 37 | |
| 38 | let capacity = arena.data.len; |
| 39 | if arena.offset >= capacity { |
| 40 | throw AllocError::OutOfMemory; |
| 41 | } |
| 42 | let address = &arena.data[0] as u64; |
| 43 | let mask = (alignment - 1) as u64; |
| 44 | let remainder = ((address & mask) + (arena.offset as u64 & mask)) & mask; |
| 45 | let padding = ((alignment as u64 - remainder) & mask) as u32; |
| 46 | let available = capacity - arena.offset; |
| 47 | if padding > available or size > available - padding { |
| 48 | throw AllocError::OutOfMemory; |
| 49 | } |
| 50 | let aligned = arena.offset + padding; |
| 51 | let base: *mut u8 = &mut arena.data[aligned]; |
| 52 | set arena.offset = aligned + size; |
| 53 | return base as *mut opaque; |
| 54 | } |
| 55 | |
| 56 | /// Allocate raw storage that remains valid until the arena is reset. |
| 57 | export unsafe fn allocRaw(arena: &mut Arena, size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError) { |
| 58 | let owner = try alloc(&mut *arena, size, alignment); |
| 59 | let byte = owner as *mut u8; |
| 60 | return &mut *byte as *unsafe mut opaque; |
| 61 | } |
| 62 | |
| 63 | /// Allocate a raw slice that remains valid until the arena is reset. |
| 64 | export unsafe fn allocRawSlice(arena: &mut Arena, size: u32, alignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError) { |
| 65 | if count == 0 { |
| 66 | return &mut []; |
| 67 | } |
| 68 | if size <> 0 and count > 4294967295 / size { |
| 69 | throw AllocError::OutOfMemory; |
| 70 | } |
| 71 | let raw = try allocRaw(arena, size * count, alignment); |
| 72 | return @sliceOf(raw, count); |
| 73 | } |
| 74 | |
| 75 | /// Raw storage provider for allocation sessions. |
| 76 | export trait Alloc { |
| 77 | /// Reserve one uninitialized object. |
| 78 | unsafe fn (&mut Alloc) reserve(size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError); |
| 79 | /// Reserve an uninitialized slice. |
| 80 | unsafe fn (&mut Alloc) reserveSlice(itemSize: u32, itemAlignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError); |
| 81 | } |
| 82 | |
| 83 | instance Alloc for Arena { |
| 84 | /// Reserve one uninitialized object in the arena. |
| 85 | unsafe fn (arena: &mut Arena) reserve(size: u32, alignment: u32) -> *unsafe mut opaque throws (AllocError) { |
| 86 | return try allocRaw(arena, size, alignment); |
| 87 | } |
| 88 | |
| 89 | /// Reserve an uninitialized slice in the arena. |
| 90 | unsafe fn (arena: &mut Arena) reserveSlice(size: u32, alignment: u32, count: u32) -> *unsafe mut [opaque] throws (AllocError) { |
| 91 | return try allocRawSlice(arena, size, alignment, count); |
| 92 | } |
| 93 | } |