Skip to content

Commit

Permalink
Make Kivi independent from Zig's std
Browse files Browse the repository at this point in the history
  • Loading branch information
devraymondsh committed Jan 24, 2024
1 parent 299a484 commit aa9a9ad
Show file tree
Hide file tree
Showing 16 changed files with 393 additions and 133 deletions.
22 changes: 16 additions & 6 deletions src/core/ByteMap.zig
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/// This is Byte(u8) hashmap implementation that relies on the caller to handle allocations and lifetimes.
const std = @import("std");
const memsimd = @import("memsimd");
const builtin = @import("builtin");
const Wyhash = @import("./Wyhash.zig");
const Math = @import("Math.zig");
const Mmap = @import("./Mmap.zig");

// Key == null and value == null : empty slot
Expand All @@ -12,6 +12,19 @@ const Entry = struct {
value: ?[]u8 = null,
};

// pub const CrtlEmpty: u8 = 0b10000000;
// pub const CrtlDeleted: u8 = 0b11111110;
// pub const CrtlSentinel: u8 = 0b11111111;
// const Crtl = packed struct(u8) {
// Empty: u8 = CrtlEmpty,
// };
// fn h1(hash: usize) usize {
// return hash >> 7;
// }
// fn h2(hash: usize) Crtl {
// return hash & 0x7f;
// }

fn nosimd_eql_byte(a: []const u8, b: []const u8) bool {
return memsimd.nosimd.eql(u8, a, b);
}
Expand All @@ -38,11 +51,10 @@ const ByteMap = @This();
table: []Entry,
table_size: usize,

var collisions: usize = 0;
var hasher = Wyhash.init(0);

pub fn init(self: *ByteMap, allocator: *Mmap, size_arg: usize) !void {
self.table_size = try std.math.ceilPowerOfTwo(usize, size_arg);
self.table_size = @intCast(Math.ceilPowerOfTwo(@intCast(size_arg)));
self.table = try allocator.alloc(Entry, self.table_size);

for (0..self.table_size) |idx| {
Expand Down Expand Up @@ -88,7 +100,6 @@ fn find_entry(self: *ByteMap, key: []const u8, comptime insertion: bool) ?*Entry
return entry;
} else {
index += 1;
collisions += 1;
}
}

Expand Down Expand Up @@ -129,6 +140,5 @@ pub fn put(self: *ByteMap, key: []u8, value: []u8) !void {

pub fn deinit(self: *ByteMap) void {
_ = self; // autofix
std.debug.print("Collisions: {any}\n", .{collisions});
collisions = 0;
// collisions = 0;
}
1 change: 0 additions & 1 deletion src/core/Kivi.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const std = @import("std");
const MMap = @import("Mmap.zig");
const memsimd = @import("memsimd");
const ByteMap = @import("ByteMap.zig");
Expand Down
32 changes: 32 additions & 0 deletions src/core/Math.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const Math = @This();

pub fn alignBackward(comptime T: type, addr: T, alignment: T) T {
// TODO: Panic
// assert(isValidAlignGeneric(T, alignment));

// 000010000 // example alignment
// 000001111 // subtract 1
// 111110000 // binary not
return addr & ~(alignment - 1);
}

pub fn alignForward(comptime T: type, addr: T, alignment: T) T {
// TODO: Panic
// assert(isValidAlignGeneric(T, alignment));

return alignBackward(T, addr + (alignment - 1), alignment);
}

pub fn ceilPowerOfTwo(n_arg: u64) u64 {
var n = n_arg;
n -= 1;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n |= n >> 32;
n += 1;

return n;
}
69 changes: 34 additions & 35 deletions src/core/Mmap.zig
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
const std = @import("std");
const builtin = @import("builtin");
const Syscall = @import("Syscall.zig");
const Math = @import("Math.zig");

const maxU32 = std.math.maxInt(u32);
const maxU64 = std.math.maxInt(u64);
const is_windows: bool = builtin.os.tag == .windows;
var empty_freelist = FreelistNode{ .len = 0, .next = null };

const FreelistNode = packed struct {
len: usize,
next: ?*FreelistNode,
};
var empty_freelist = FreelistNode{ .len = 0, .next = null };

cursor: usize,
freelist: *FreelistNode,
mem: []align(std.mem.page_size) u8,
page_size: usize,
mem: []align(Syscall.page_size) u8,
mprotect_size: usize,
protected_mem_cursor: usize,

const Mmap = @This();
Expand All @@ -27,37 +26,39 @@ pub fn byte_slice_cast(comptime T: type, value: []u8) []T {
}

fn mprotect(self: *Mmap) !void {
const protected_mem_cursor = self.protected_mem_cursor + self.page_size;
const protected_mem_cursor = self.protected_mem_cursor + self.mprotect_size;

if (!is_windows) {
try std.os.mprotect(@alignCast(self.mem[self.protected_mem_cursor..protected_mem_cursor]), std.os.PROT.READ | std.os.PROT.WRITE);
try Syscall.mprotect(@alignCast(self.mem[self.protected_mem_cursor..protected_mem_cursor]), Syscall.PROT.READ | Syscall.PROT.WRITE);
} else {
const std = @import("std");
_ = try std.os.windows.VirtualAlloc(@ptrCast(@alignCast(self.mem)), protected_mem_cursor, std.os.windows.MEM_COMMIT, std.os.windows.PAGE_READWRITE);
}

self.protected_mem_cursor = protected_mem_cursor;
}

pub fn init(total_size: usize, page_size: usize) !Mmap {
var mem: []align(std.mem.page_size) u8 = undefined;
const size = std.mem.alignForward(usize, total_size, std.mem.page_size);
pub fn init(total_size: usize, mprotect_size: usize) !Mmap {
var mem: []align(Syscall.page_size) u8 = undefined;
const size = Math.alignForward(usize, total_size, Syscall.page_size);
if (!is_windows) {
mem = try std.os.mmap(
mem = try Syscall.mmap(
null,
size,
std.os.PROT.NONE,
std.os.MAP.ANONYMOUS | std.os.MAP.PRIVATE,
Syscall.PROT.NONE,
Syscall.MAP.ANONYMOUS | Syscall.MAP.PRIVATE,
-1,
0,
);
} else {
const std = @import("std");
const lpvoid = try std.os.windows.VirtualAlloc(null, size, std.os.windows.MEM_RESERVE, std.os.windows.PAGE_NOACCESS);

mem.len = size;
mem.ptr = @alignCast(@ptrCast(lpvoid));
}

var mmap = Mmap{ .mem = mem, .cursor = 0, .protected_mem_cursor = 0, .freelist = &empty_freelist, .page_size = std.mem.alignForward(usize, page_size, std.mem.page_size) };
var mmap = Mmap{ .mem = mem, .cursor = 0, .protected_mem_cursor = 0, .freelist = &empty_freelist, .mprotect_size = Math.alignForward(usize, mprotect_size, Syscall.page_size) };
mmap.mprotect() catch unreachable;

return mmap;
Expand Down Expand Up @@ -87,7 +88,7 @@ pub fn alloc_byte(self: *Mmap, size: usize) ![]u8 {
const starting_pos = self.cursor;
var ending_pos: usize = starting_pos + 16;
if (size > 16) {
ending_pos += std.mem.alignForward(usize, size - 16, 8);
ending_pos += Math.alignForward(usize, size - 16, 8);
}

if (ending_pos > self.protected_mem_cursor) {
Expand All @@ -110,30 +111,28 @@ pub fn alloc(self: *Mmap, comptime T: type, n: usize) ![]T {
}

pub fn free(self: *Mmap, data: []u8) void {
_ = self; // autofix
_ = data; // autofix
// const freelist = @as(*FreelistNode, @alignCast(@ptrCast(data.ptr)));

// if (data.len > 16) {
// freelist.len = @intCast(std.mem.alignForward(usize, data.len, 8));
// } else {
// freelist.len = 16;
// }

// if (self.freelist.len != 0) {
// freelist.next = self.freelist;
// } else {
// freelist.next = null;
// }

// self.freelist = freelist;
return;
const freelist = @as(*FreelistNode, @alignCast(@ptrCast(data.ptr)));

if (data.len > 16) {
freelist.len = @intCast(Math.alignForward(usize, data.len, 8));
} else {
freelist.len = 16;
}

if (self.freelist.len != 0) {
freelist.next = self.freelist;
} else {
freelist.next = null;
}

self.freelist = freelist;
}

pub fn deinit(self: *Mmap) void {
if (!is_windows) {
std.os.munmap(self.mem);
Syscall.unmap(self.mem);
} else {
const std = @import("std");
std.os.windows.VirtualFree(@alignCast(@ptrCast(self.mem.ptr)), 0, std.os.windows.MEM_RELEASE);
}
}
Loading

0 comments on commit aa9a9ad

Please sign in to comment.