From 4ebe1b2bceb4c0d3b93ed70fc55e5d1dc5ac9946 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Wed, 5 Oct 2022 08:11:02 -0700 Subject: [PATCH] Avoid allocating a new list when calling List.sublist --- crates/compiler/builtins/bitcode/src/list.zig | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index 467ee2ff37..e244cbe45f 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -517,17 +517,25 @@ pub fn listSublist( len: usize, dec: Dec, ) callconv(.C) RocList { - if (len == 0) { + const size = list.len(); + if (len == 0 or start >= size) { + if (list.isUnique()) { + // Decrement the reference counts of all elements. + if (list.bytes) |source_ptr| { + var i: usize = 0; + while (i < size) : (i += 1) { + const element = source_ptr + i * element_width; + dec(element); + } + var output = list; + output.length = 0; + return output; + } + } return RocList.empty(); } if (list.bytes) |source_ptr| { - const size = list.len(); - - if (start >= size) { - return RocList.empty(); - } - const keep_len = std.math.min(len, size - start); const drop_start_len = start; const drop_end_len = size - (start + keep_len); @@ -546,10 +554,17 @@ pub fn listSublist( dec(element); } - if (start == 0 and list.isUnique()) { + if (list.isUnique()) { var output = list; output.length = keep_len; - return output; + if (start == 0) { + return output; + } else { + // We want memmove due to aliasing. Zig does not expose it directly. + // Instead use copy which can write to aliases as long as the dest is before the source. + mem.copy(u8, source_ptr[0 .. keep_len * element_width], source_ptr[start * element_width .. (start + keep_len) * element_width]); + return output; + } } else { const output = RocList.allocate(alignment, keep_len, element_width); const target_ptr = output.bytes orelse unreachable;