optimize zig code

This commit is contained in:
Folkert 2021-05-23 15:58:08 +02:00
parent 53871317d5
commit a4ed13d714
4 changed files with 114 additions and 15 deletions

View file

@ -912,19 +912,28 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: usize, element_wi
return output;
}
// input: RocList,
pub fn listSet(
input: RocList,
bytes: ?[*]u8,
length: usize,
alignment: usize,
index: usize,
element: Opaque,
element_width: usize,
dec: Dec,
) callconv(.C) RocList {
if (index < input.len()) {
var list = input.makeUnique(std.heap.c_allocator, alignment, element_width);
) callconv(.C) ?[*]u8 {
// INVARIANT: bounds checking happens on the roc side
//
// at the time of writing, the function is implemented roughly as
// `if inBounds then LowLevelListGet input index item else input`
// so we don't do a bounds check here. Hence, the list is also non-empty,
// because inserting into an empty list is always out of bounds
const ptr: [*]usize = @ptrCast([*]usize, @alignCast(8, bytes));
if ((ptr - 1)[0] == utils.REFCOUNT_ONE) {
// the element we will replace
var element_at_index = (list.bytes orelse undefined) + (index * element_width);
var element_at_index = (bytes orelse undefined) + (index * element_width);
// decrement its refcount
dec(element_at_index);
@ -932,12 +941,40 @@ pub fn listSet(
// copy in the new element
@memcpy(element_at_index, element orelse undefined, element_width);
return list;
return bytes;
} else {
// we're out of bounds, and will not be using the `element`.
// but we must consume the RC token, so explicitly decrement
dec(element);
return input;
return listSetClone(bytes, length, alignment, index, element, element_width, dec);
}
}
inline fn listSetClone(
old_bytes: ?[*]u8,
length: usize,
alignment: usize,
index: usize,
element: Opaque,
element_width: usize,
dec: Dec,
) ?[*]u8 {
@setCold(true);
const data_bytes = length * element_width;
var new_bytes = utils.mallocWithRefcount(alignment, data_bytes);
@memcpy(new_bytes, old_bytes orelse undefined, data_bytes);
// the element we will replace
var element_at_index = new_bytes + (index * element_width);
// decrement its refcount
dec(element_at_index);
// copy in the new element
@memcpy(element_at_index, element orelse undefined, element_width);
// TODO decref the input list!
//return list;
return new_bytes;
}