add lowlevel to inc/dec a data pointer

This commit is contained in:
Folkert 2023-04-28 15:30:23 +02:00
parent a61e7a696d
commit cf54304cf4
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
13 changed files with 90 additions and 28 deletions

View file

@ -974,7 +974,7 @@ test "listConcat: non-unique with unique overlapping" {
var bytes: [*]u8 = @ptrCast([*]u8, nonUnique.bytes);
const ptr_width = @sizeOf(usize);
const refcount_ptr = @ptrCast([*]isize, @alignCast(ptr_width, bytes) - ptr_width);
utils.increfC(&refcount_ptr[0], 1);
utils.increfRcPtrC(&refcount_ptr[0], 1);
defer nonUnique.decref(@sizeOf(u8)); // listConcat will dec the other refcount
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);

View file

@ -173,8 +173,10 @@ comptime {
// Utils
comptime {
exportUtilsFn(utils.test_panic, "test_panic");
exportUtilsFn(utils.increfC, "incref");
exportUtilsFn(utils.decrefC, "decref");
exportUtilsFn(utils.increfRcPtrC, "incref_rc_ptr");
exportUtilsFn(utils.decrefRcPtrC, "decref_rc_ptr");
exportUtilsFn(utils.increfDataPtrC, "incref_data_ptr");
exportUtilsFn(utils.decrefDataPtrC, "decref_data_ptr");
exportUtilsFn(utils.isUnique, "is_unique");
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount");

View file

@ -162,7 +162,7 @@ pub const RocStr = extern struct {
const ref_ptr = self.getRefcountPtr();
if (ref_ptr != null) {
const isizes: [*]isize = @ptrCast([*]isize, @alignCast(@alignOf(isize), ref_ptr));
utils.increfC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
utils.increfRcPtrC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
}
}
}

View file

@ -147,7 +147,7 @@ const Refcount = enum {
const RC_TYPE = Refcount.normal;
pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
if (RC_TYPE == Refcount.none) return;
// Ensure that the refcount is not whole program lifetime.
if (ptr_to_refcount.* != REFCOUNT_MAX_ISIZE) {
@ -165,7 +165,7 @@ pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
}
}
pub fn decrefC(
pub fn decrefRcPtrC(
bytes_or_null: ?[*]isize,
alignment: u32,
) callconv(.C) void {
@ -188,6 +188,36 @@ pub fn decrefCheckNullC(
}
}
pub fn decrefDataPtrC(
bytes_or_null: ?[*]isize,
alignment: u32,
) callconv(.C) void {
var bytes = bytes_or_null orelse return;
const ptr = @ptrToInt(bytes);
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
const masked_ptr = ptr & ~tag_mask;
const isizes: [*]isize = @intToPtr([*]isize, masked_ptr);
return decrefRcPtrC(isizes - 1, alignment);
}
pub fn increfDataPtrC(
bytes_or_null: ?[*]isize,
inc_amount: isize,
) callconv(.C) void {
var bytes = bytes_or_null orelse return;
const ptr = @ptrToInt(bytes);
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
const masked_ptr = ptr & ~tag_mask;
const isizes: *isize = @intToPtr(*isize, masked_ptr - @sizeOf(usize));
return increfRcPtrC(isizes, inc_amount);
}
pub fn decref(
bytes_or_null: ?[*]u8,
data_bytes: usize,
@ -363,13 +393,13 @@ pub const UpdateMode = enum(u8) {
test "increfC, refcounted data" {
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
var ptr_to_refcount: *isize = &mock_rc;
increfC(ptr_to_refcount, 2);
increfRcPtrC(ptr_to_refcount, 2);
try std.testing.expectEqual(mock_rc, REFCOUNT_ONE_ISIZE + 19);
}
test "increfC, static data" {
var mock_rc: isize = REFCOUNT_MAX_ISIZE;
var ptr_to_refcount: *isize = &mock_rc;
increfC(ptr_to_refcount, 2);
increfRcPtrC(ptr_to_refcount, 2);
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
}