mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
stop aliasing in dictWalk
This commit is contained in:
parent
1a39fa201c
commit
48dee993d0
1 changed files with 16 additions and 9 deletions
|
@ -761,28 +761,35 @@ pub fn setFromList(list: RocList, alignment: Alignment, key_width: usize, value_
|
||||||
|
|
||||||
const StepperCaller = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
const StepperCaller = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||||
pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, accum: Opaque, alignment: Alignment, key_width: usize, value_width: usize, accum_width: usize, inc_key: Inc, inc_value: Inc, output: Opaque) callconv(.C) void {
|
pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, accum: Opaque, alignment: Alignment, key_width: usize, value_width: usize, accum_width: usize, inc_key: Inc, inc_value: Inc, output: Opaque) callconv(.C) void {
|
||||||
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
|
// allocate space to write the result of the stepper into
|
||||||
|
// experimentally aliasing the accum and output pointers is not a good idea
|
||||||
|
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
||||||
|
var b1 = output orelse unreachable;
|
||||||
|
var b2 = alloc;
|
||||||
|
|
||||||
|
@memcpy(b2, accum orelse unreachable, accum_width);
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
const size = dict.capacity();
|
const size = dict.capacity();
|
||||||
while (i < size) : (i += 1) {
|
while (i < size) : (i += 1) {
|
||||||
switch (dict.getSlot(i, key_width, value_width)) {
|
switch (dict.getSlot(i, key_width, value_width)) {
|
||||||
Slot.Filled => {
|
Slot.Filled => {
|
||||||
if (value_width == 0) {
|
const key = dict.getKey(i, alignment, key_width, value_width);
|
||||||
const key = dict.getKey(i, alignment, key_width, value_width);
|
const value = dict.getValue(i, alignment, key_width, value_width);
|
||||||
|
|
||||||
stepper_caller(stepper, key, null, output, output);
|
stepper_caller(stepper, key, value, b2, b1);
|
||||||
} else {
|
|
||||||
const key = dict.getKey(i, alignment, key_width, value_width);
|
|
||||||
const value = dict.getValue(i, alignment, key_width, value_width);
|
|
||||||
|
|
||||||
stepper_caller(stepper, key, value, output, output);
|
const temp = b1;
|
||||||
}
|
b2 = b1;
|
||||||
|
b1 = temp;
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@memcpy(output orelse unreachable, b2, accum_width);
|
||||||
|
std.heap.c_allocator.free(alloc[0..accum_width]);
|
||||||
|
|
||||||
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
|
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
|
||||||
decref(std.heap.c_allocator, alignment, dict.dict_bytes, data_bytes);
|
decref(std.heap.c_allocator, alignment, dict.dict_bytes, data_bytes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue