Switch builtins to use roc_alloc and friends

This commit is contained in:
Richard Feldman 2021-05-22 22:05:19 -04:00
parent 8cafabc0c9
commit ab51582541
4 changed files with 299 additions and 297 deletions

View file

@ -2,7 +2,6 @@ const std = @import("std");
const testing = std.testing;
const expectEqual = testing.expectEqual;
const mem = std.mem;
const Allocator = mem.Allocator;
const assert = std.debug.assert;
const utils = @import("utils.zig");
@ -94,20 +93,18 @@ const Alignment = packed enum(u8) {
};
pub fn decref(
allocator: *Allocator,
alignment: Alignment,
bytes_or_null: ?[*]u8,
data_bytes: usize,
) void {
return utils.decref(allocator, alignment.toUsize(), bytes_or_null, data_bytes);
return utils.decref(alignment.toUsize(), bytes_or_null, data_bytes);
}
pub fn allocateWithRefcount(
allocator: *Allocator,
alignment: Alignment,
data_bytes: usize,
) [*]u8 {
return utils.allocateWithRefcount(allocator, alignment.toUsize(), data_bytes);
return utils.allocateWithRefcount(alignment.toUsize(), data_bytes);
}
pub const RocDict = extern struct {
@ -124,7 +121,6 @@ pub const RocDict = extern struct {
}
pub fn allocate(
allocator: *Allocator,
number_of_levels: usize,
number_of_entries: usize,
alignment: Alignment,
@ -136,7 +132,7 @@ pub const RocDict = extern struct {
const data_bytes = number_of_slots * slot_size;
return RocDict{
.dict_bytes = allocateWithRefcount(allocator, alignment, data_bytes),
.dict_bytes = allocateWithRefcount(alignment, data_bytes),
.number_of_levels = number_of_levels,
.dict_entries_len = number_of_entries,
};
@ -144,7 +140,6 @@ pub const RocDict = extern struct {
pub fn reallocate(
self: RocDict,
allocator: *Allocator,
alignment: Alignment,
key_width: usize,
value_width: usize,
@ -157,7 +152,7 @@ pub const RocDict = extern struct {
const delta_capacity = new_capacity - old_capacity;
const data_bytes = new_capacity * slot_size;
const first_slot = allocateWithRefcount(allocator, alignment, data_bytes);
const first_slot = allocateWithRefcount(alignment, data_bytes);
// transfer the memory
@ -204,7 +199,7 @@ pub const RocDict = extern struct {
};
// NOTE we fuse an increment of all keys/values with a decrement of the input dict
decref(allocator, alignment, self.dict_bytes, self.capacity() * slotSize(key_width, value_width));
decref(alignment, self.dict_bytes, self.capacity() * slotSize(key_width, value_width));
return result;
}
@ -236,7 +231,7 @@ pub const RocDict = extern struct {
return totalCapacityAtLevel(self.number_of_levels);
}
pub fn makeUnique(self: RocDict, allocator: *Allocator, alignment: Alignment, key_width: usize, value_width: usize) RocDict {
pub fn makeUnique(self: RocDict, alignment: Alignment, key_width: usize, value_width: usize) RocDict {
if (self.isEmpty()) {
return self;
}
@ -246,7 +241,7 @@ pub const RocDict = extern struct {
}
// unfortunately, we have to clone
var new_dict = RocDict.allocate(allocator, self.number_of_levels, self.dict_entries_len, alignment, key_width, value_width);
var new_dict = RocDict.allocate(self.number_of_levels, self.dict_entries_len, alignment, key_width, value_width);
var old_bytes: [*]u8 = @ptrCast([*]u8, self.dict_bytes);
var new_bytes: [*]u8 = @ptrCast([*]u8, new_dict.dict_bytes);
@ -256,7 +251,7 @@ pub const RocDict = extern struct {
// NOTE we fuse an increment of all keys/values with a decrement of the input dict
const data_bytes = self.capacity() * slotSize(key_width, value_width);
decref(allocator, alignment, self.dict_bytes, data_bytes);
decref(alignment, self.dict_bytes, data_bytes);
return new_dict;
}
@ -420,7 +415,7 @@ const Dec = fn (?[*]u8) callconv(.C) void;
pub fn dictInsert(input: RocDict, alignment: Alignment, key: Opaque, key_width: usize, value: Opaque, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Dec, dec_value: Dec, output: *RocDict) callconv(.C) void {
var seed: u64 = INITIAL_SEED;
var result = input.makeUnique(std.heap.c_allocator, alignment, key_width, value_width);
var result = input.makeUnique(alignment, key_width, value_width);
var current_level: usize = 1;
var current_level_size: usize = 8;
@ -428,7 +423,7 @@ pub fn dictInsert(input: RocDict, alignment: Alignment, key: Opaque, key_width:
while (true) {
if (current_level > result.number_of_levels) {
result = result.reallocate(std.heap.c_allocator, alignment, key_width, value_width);
result = result.reallocate(alignment, key_width, value_width);
}
const hash = hash_fn(seed, key);
@ -484,7 +479,7 @@ pub fn dictRemove(input: RocDict, alignment: Alignment, key: Opaque, key_width:
return;
},
MaybeIndex.index => |index| {
var dict = input.makeUnique(std.heap.c_allocator, alignment, key_width, value_width);
var dict = input.makeUnique(alignment, key_width, value_width);
assert(index < dict.capacity());
@ -499,7 +494,7 @@ pub fn dictRemove(input: RocDict, alignment: Alignment, key: Opaque, key_width:
// if the dict is now completely empty, free its allocation
if (dict.dict_entries_len == 0) {
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
decref(std.heap.c_allocator, alignment, dict.dict_bytes, data_bytes);
decref(alignment, dict.dict_bytes, data_bytes);
output.* = RocDict.empty();
return;
}
@ -572,7 +567,7 @@ pub fn dictKeys(dict: RocDict, alignment: Alignment, key_width: usize, value_wid
}
const data_bytes = length * key_width;
var ptr = allocateWithRefcount(std.heap.c_allocator, alignment, data_bytes);
var ptr = allocateWithRefcount(alignment, data_bytes);
var offset = blk: {
if (alignment.keyFirst()) {
@ -621,7 +616,7 @@ pub fn dictValues(dict: RocDict, alignment: Alignment, key_width: usize, value_w
}
const data_bytes = length * value_width;
var ptr = allocateWithRefcount(std.heap.c_allocator, alignment, data_bytes);
var ptr = allocateWithRefcount(alignment, data_bytes);
var offset = blk: {
if (alignment.keyFirst()) {
@ -655,7 +650,7 @@ fn doNothing(ptr: Opaque) callconv(.C) void {
}
pub fn dictUnion(dict1: RocDict, dict2: RocDict, alignment: Alignment, key_width: usize, value_width: usize, hash_fn: HashFn, is_eq: EqFn, inc_key: Inc, inc_value: Inc, output: *RocDict) callconv(.C) void {
output.* = dict1.makeUnique(std.heap.c_allocator, alignment, key_width, value_width);
output.* = dict1.makeUnique(alignment, key_width, value_width);
var i: usize = 0;
while (i < dict2.capacity()) : (i += 1) {
@ -690,7 +685,7 @@ pub fn dictUnion(dict1: RocDict, dict2: RocDict, alignment: Alignment, key_width
}
pub fn dictIntersection(dict1: RocDict, dict2: RocDict, alignment: Alignment, key_width: usize, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Inc, dec_value: Inc, output: *RocDict) callconv(.C) void {
output.* = dict1.makeUnique(std.heap.c_allocator, alignment, key_width, value_width);
output.* = dict1.makeUnique(alignment, key_width, value_width);
var i: usize = 0;
const size = dict1.capacity();
@ -715,7 +710,7 @@ pub fn dictIntersection(dict1: RocDict, dict2: RocDict, alignment: Alignment, ke
}
pub fn dictDifference(dict1: RocDict, dict2: RocDict, alignment: Alignment, key_width: usize, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Dec, dec_value: Dec, output: *RocDict) callconv(.C) void {
output.* = dict1.makeUnique(std.heap.c_allocator, alignment, key_width, value_width);
output.* = dict1.makeUnique(alignment, key_width, value_width);
var i: usize = 0;
const size = dict1.capacity();
@ -756,16 +751,17 @@ pub fn setFromList(list: RocList, alignment: Alignment, key_width: usize, value_
// NOTE: decref checks for the empty case
const data_bytes = size * key_width;
decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
decref(alignment, list.bytes, data_bytes);
}
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 {
const alignment_usize = alignment.toUsize();
// 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);
const bytes_ptr: [*]u8 = utils.alloc(alignment_usize, accum_width);
var b1 = output orelse unreachable;
var b2 = alloc;
var b2 = bytes_ptr;
@memcpy(b2, accum orelse unreachable, accum_width);
@ -788,8 +784,8 @@ pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, a
}
@memcpy(output orelse unreachable, b2, accum_width);
std.heap.c_allocator.free(alloc[0..accum_width]);
utils.dealloc(alignment_usize, bytes_ptr);
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
decref(std.heap.c_allocator, alignment, dict.dict_bytes, data_bytes);
decref(alignment, dict.dict_bytes, data_bytes);
}