mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge remote-tracking branch 'origin/roc_alloc' into zig-list-set
This commit is contained in:
commit
91b49ecf98
30 changed files with 940 additions and 631 deletions
|
@ -1,5 +1,53 @@
|
|||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const always_inline = std.builtin.CallOptions.Modifier.always_inline;
|
||||
|
||||
// If allocation fails, this must cxa_throw - it must not return a null pointer!
|
||||
extern fn roc_alloc(alignment: usize, size: usize) callconv(.C) *c_void;
|
||||
|
||||
// This should never be passed a null pointer.
|
||||
// If allocation fails, this must cxa_throw - it must not return a null pointer!
|
||||
extern fn roc_realloc(alignment: usize, c_ptr: *c_void, old_size: usize, new_size: usize) callconv(.C) *c_void;
|
||||
|
||||
// This should never be passed a null pointer.
|
||||
extern fn roc_dealloc(alignment: usize, c_ptr: *c_void) callconv(.C) void;
|
||||
|
||||
comptime {
|
||||
// During tetsts, use the testing allocators to satisfy these functions.
|
||||
if (std.builtin.is_test) {
|
||||
@export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong });
|
||||
@export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .Strong });
|
||||
@export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .Strong });
|
||||
}
|
||||
}
|
||||
|
||||
fn testing_roc_alloc(alignment: usize, size: usize) callconv(.C) *c_void {
|
||||
return @ptrCast(*c_void, std.testing.allocator.alloc(u8, size) catch unreachable);
|
||||
}
|
||||
|
||||
fn testing_roc_realloc(alignment: usize, c_ptr: *c_void, old_size: usize, new_size: usize) callconv(.C) *c_void {
|
||||
const ptr = @ptrCast([*]u8, @alignCast(16, c_ptr));
|
||||
const slice = ptr[0..old_size];
|
||||
|
||||
return @ptrCast(*c_void, std.testing.allocator.realloc(slice, new_size) catch unreachable);
|
||||
}
|
||||
|
||||
fn testing_roc_dealloc(alignment: usize, c_ptr: *c_void) callconv(.C) void {
|
||||
const ptr = @ptrCast([*]u8, @alignCast(16, c_ptr));
|
||||
|
||||
std.testing.allocator.destroy(ptr);
|
||||
}
|
||||
|
||||
pub fn alloc(alignment: usize, size: usize) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_alloc, .{ alignment, size }));
|
||||
}
|
||||
|
||||
pub fn realloc(alignment: usize, c_ptr: [*]u8, old_size: usize, new_size: usize) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_realloc, .{ alignment, c_ptr, old_size, new_size }));
|
||||
}
|
||||
|
||||
pub fn dealloc(alignment: usize, c_ptr: [*]u8) void {
|
||||
return @call(.{ .modifier = always_inline }, roc_dealloc, .{ alignment, c_ptr });
|
||||
}
|
||||
|
||||
pub const Inc = fn (?[*]u8) callconv(.C) void;
|
||||
pub const IncN = fn (?[*]u8, u64) callconv(.C) void;
|
||||
|
@ -62,7 +110,6 @@ pub fn intWidth(width: IntWidth) anytype {
|
|||
}
|
||||
|
||||
pub fn decref(
|
||||
allocator: *Allocator,
|
||||
alignment: usize,
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
|
@ -81,7 +128,7 @@ pub fn decref(
|
|||
switch (alignment) {
|
||||
16 => {
|
||||
if (refcount == REFCOUNT_ONE_ISIZE) {
|
||||
allocator.free((bytes - 16)[0 .. 16 + data_bytes]);
|
||||
dealloc(alignment, bytes - 16);
|
||||
} else if (refcount_isize < 0) {
|
||||
(isizes - 1)[0] = refcount - 1;
|
||||
}
|
||||
|
@ -89,7 +136,7 @@ pub fn decref(
|
|||
else => {
|
||||
// NOTE enums can currently have an alignment of < 8
|
||||
if (refcount == REFCOUNT_ONE_ISIZE) {
|
||||
allocator.free((bytes - 8)[0 .. 8 + data_bytes]);
|
||||
dealloc(alignment, bytes - 8);
|
||||
} else if (refcount_isize < 0) {
|
||||
(isizes - 1)[0] = refcount - 1;
|
||||
}
|
||||
|
@ -98,7 +145,6 @@ pub fn decref(
|
|||
}
|
||||
|
||||
pub fn allocateWithRefcount(
|
||||
allocator: *Allocator,
|
||||
alignment: usize,
|
||||
data_bytes: usize,
|
||||
) [*]u8 {
|
||||
|
@ -108,7 +154,7 @@ pub fn allocateWithRefcount(
|
|||
16 => {
|
||||
const length = 2 * @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: []align(16) u8 = allocator.alignedAlloc(u8, 16, length) catch unreachable;
|
||||
var new_bytes: [*]align(16) u8 = @alignCast(16, alloc(alignment, length));
|
||||
|
||||
var as_usize_array = @ptrCast([*]usize, new_bytes);
|
||||
if (result_in_place) {
|
||||
|
@ -127,13 +173,13 @@ pub fn allocateWithRefcount(
|
|||
else => {
|
||||
const length = @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: []align(8) u8 = allocator.alignedAlloc(u8, 8, length) catch unreachable;
|
||||
var new_bytes: [*]align(8) u8 = @alignCast(8, alloc(alignment, length));
|
||||
|
||||
var as_usize_array = @ptrCast([*]isize, new_bytes);
|
||||
var as_isize_array = @ptrCast([*]isize, new_bytes);
|
||||
if (result_in_place) {
|
||||
as_usize_array[0] = @intCast(isize, number_of_slots);
|
||||
as_isize_array[0] = @intCast(isize, number_of_slots);
|
||||
} else {
|
||||
as_usize_array[0] = REFCOUNT_ONE_ISIZE;
|
||||
as_isize_array[0] = REFCOUNT_ONE_ISIZE;
|
||||
}
|
||||
|
||||
var as_u8_array = @ptrCast([*]u8, new_bytes);
|
||||
|
@ -192,7 +238,6 @@ pub fn mallocWithRefcount(
|
|||
|
||||
pub fn unsafeReallocate(
|
||||
source_ptr: [*]u8,
|
||||
allocator: *Allocator,
|
||||
alignment: usize,
|
||||
old_length: usize,
|
||||
new_length: usize,
|
||||
|
@ -211,8 +256,8 @@ pub fn unsafeReallocate(
|
|||
|
||||
// TODO handle out of memory
|
||||
// NOTE realloc will dealloc the original allocation
|
||||
const old_allocation = (source_ptr - align_width)[0..old_width];
|
||||
const new_allocation = allocator.realloc(old_allocation, new_width) catch unreachable;
|
||||
const old_allocation = source_ptr - align_width;
|
||||
const new_allocation = realloc(alignment, old_allocation, old_width, new_width);
|
||||
|
||||
const new_source = @ptrCast([*]u8, new_allocation) + align_width;
|
||||
return new_source;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue