Merge remote-tracking branch 'origin/roc_alloc' into zig-list-set

This commit is contained in:
Folkert 2021-05-24 18:25:18 +02:00
commit 91b49ecf98
30 changed files with 940 additions and 631 deletions

View file

@ -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;