Create new lowlevels for refcounting

This commit is contained in:
Brian Carroll 2021-11-24 16:07:31 +00:00
parent c8278dcb1c
commit 6e5acadfea
7 changed files with 34 additions and 0 deletions

View File

@ -138,6 +138,7 @@ comptime {
comptime {
exportUtilsFn(utils.test_panic, "test_panic");
exportUtilsFn(utils.increfC, "incref");
exportUtilsFn(utils.decrefC, "decref");
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");

View File

@ -104,6 +104,12 @@ pub const IntWidth = enum(u8) {
I128 = 9,
};
pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
var refcount = ptr_to_refcount.*;
var masked_amount = if (refcount == REFCOUNT_MAX_ISIZE) 0 else amount;
ptr_to_refcount.* = refcount + masked_amount;
}
pub fn decrefC(
bytes_or_null: ?[*]isize,
alignment: u32,
@ -261,3 +267,17 @@ pub const UpdateMode = enum(u8) {
Immutable = 0,
InPlace = 1,
};
test "increfC, refcounted data" {
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
var ptr_to_refcount: *isize = &mock_rc;
increfC(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);
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
}

View File

@ -309,5 +309,6 @@ pub const DEC_MUL_WITH_OVERFLOW: &str = "roc_builtins.dec.mul_with_overflow";
pub const DEC_DIV: &str = "roc_builtins.dec.div";
pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";

View File

@ -6020,6 +6020,10 @@ fn run_low_level<'a, 'ctx, 'env>(
| ListAny | ListAll | ListFindUnsafe | DictWalk => {
unreachable!("these are higher order, and are handled elsewhere")
}
RefCountGetPtr | RefCountInc | RefCountDec => {
unreachable!("LLVM backend does not use lowlevels for refcounting");
}
}
}

View File

@ -370,6 +370,7 @@ pub fn decode_low_level<'a>(
Not => code_builder.i32_eqz(),
Hash => return NotImplemented,
ExpectTrue => return NotImplemented,
RefCountGetPtr | RefCountInc | RefCountDec => return NotImplemented,
}
Done
}

View File

@ -115,6 +115,9 @@ pub enum LowLevel {
Not,
Hash,
ExpectTrue,
RefCountGetPtr,
RefCountInc,
RefCountDec,
}
macro_rules! higher_order {

View File

@ -1008,6 +1008,10 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
SetFromList => arena.alloc_slice_copy(&[owned]),
ExpectTrue => arena.alloc_slice_copy(&[irrelevant]),
RefCountGetPtr | RefCountInc | RefCountDec => {
unreachable!("Refcounting lowlevel calls are inserted *after* borrow checking");
}
}
}