diff --git a/crates/compiler/builtins/bitcode/src/utils.zig b/crates/compiler/builtins/bitcode/src/utils.zig index 1fbd07e55b..9546bf6cf3 100644 --- a/crates/compiler/builtins/bitcode/src/utils.zig +++ b/crates/compiler/builtins/bitcode/src/utils.zig @@ -1,7 +1,10 @@ const std = @import("std"); +const builtin = @import("builtin"); const always_inline = std.builtin.CallOptions.Modifier.always_inline; const Monotonic = std.builtin.AtomicOrder.Monotonic; +const DEBUG_INCDEC = false; + pub fn WithOverflow(comptime T: type) type { return extern struct { value: T, has_overflowed: bool }; } @@ -40,7 +43,6 @@ fn testing_roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int } comptime { - const builtin = @import("builtin"); // During tests, use the testing allocators to satisfy these functions. if (builtin.is_test) { @export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong }); @@ -156,7 +158,18 @@ pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void { // As such, we do not need to cap incrementing. switch (RC_TYPE) { Refcount.normal => { + const old = @intCast(usize, ptr_to_refcount.*); ptr_to_refcount.* += amount; + const new = @intCast(usize, ptr_to_refcount.*); + + if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { + const stdout = std.io.getStdOut().writer(); + + const oldH = old - REFCOUNT_ONE + 1; + const newH = new - REFCOUNT_ONE + 1; + + stdout.print("| increment {*}: {} + {} = {}!\n", .{ ptr_to_refcount, oldH, amount, newH }) catch unreachable; + } }, Refcount.atomic => { _ = @atomicRmw(isize, ptr_to_refcount, std.builtin.AtomicRmwOp.Add, amount, Monotonic); @@ -246,7 +259,19 @@ inline fn decref_ptr_to_refcount( if (refcount != REFCOUNT_MAX_ISIZE) { switch (RC_TYPE) { Refcount.normal => { + const old = @intCast(usize, refcount); refcount_ptr[0] = refcount -% 1; + const new = @intCast(usize, refcount -% 1); + + if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { + const stdout = std.io.getStdOut().writer(); + + const oldH = old - REFCOUNT_ONE + 1; + const newH = new - REFCOUNT_ONE + 1; + + stdout.print("| decrement {*}: {} - 1 = {}!\n", .{ refcount_ptr, oldH, newH }) catch unreachable; + } + if (refcount == REFCOUNT_ONE_ISIZE) { dealloc(@ptrCast([*]u8, refcount_ptr) - (extra_bytes - @sizeOf(usize)), alignment); } diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index ab8a45507b..d889578bdd 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -45,6 +45,10 @@ impl HelperOp { fn is_dec(&self) -> bool { matches!(self, Self::Dec) } + + fn is_inc(&self) -> bool { + matches!(self, Self::Inc) + } } #[derive(Debug)] diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 779cdd9f58..afb84430da 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -860,23 +860,23 @@ fn refcount_list<'a>( arena.alloc(ret_stmt), ); - let modify_elems_and_list = - if layout_interner.get(elem_layout).is_refcounted() && ctx.op.is_dec() { - refcount_list_elems( - root, - ident_ids, - ctx, - layout_interner, - elem_layout, - LAYOUT_UNIT, - box_layout, - len, - elements, - modify_list, - ) - } else { - modify_list - }; + let relevant_op = ctx.op.is_dec() || ctx.op.is_inc(); + let modify_elems_and_list = if relevant_op && layout_interner.get(elem_layout).is_refcounted() { + refcount_list_elems( + root, + ident_ids, + ctx, + layout_interner, + elem_layout, + LAYOUT_UNIT, + box_layout, + len, + elements, + modify_list, + ) + } else { + modify_list + }; // // Do nothing if the list is empty