From 476632d9559b1e3bacbd226df336116cac8544ea Mon Sep 17 00:00:00 2001 From: Taylan Kammer Date: Mon, 22 Jun 2026 18:22:36 +0200 Subject: Improvements. --- src/main.zig | 21 +++++++++++++-------- src/zisp/gc/ListPool.zig | 25 ++++++++++++++++++------- src/zisp/value.zig | 14 +++++++------- src/zisp/value/list.zig | 33 +++++++++++++++++++++++---------- 4 files changed, 61 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/main.zig b/src/main.zig index e601020..d08f9a1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,21 +1,25 @@ const std = @import("std"); const zisp = @import("zisp"); +const gc = zisp.gc; +const io = zisp.io; +const value = zisp.value; + pub fn main() !u8 { const alloc = std.heap.smp_allocator; - const io = std.Io.Threaded.global_single_threaded.io(); + const gst_io = std.Io.Threaded.global_single_threaded.io(); var stdin_buffer: [4096]u8 = undefined; - var stdin_reader = std.Io.File.stdin().reader(io, &stdin_buffer); + var stdin_reader = std.Io.File.stdin().reader(gst_io, &stdin_buffer); const reader = &stdin_reader.interface; var stdout_buffer: [4096]u8 = undefined; - var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer); + var stdout_writer = std.Io.File.stdout().writer(gst_io, &stdout_buffer); const writer = &stdout_writer.interface; - try zisp.gc.init(); + try gc.init(); - var p = try zisp.io.Parser.init(alloc); + var p = try io.Parser.init(alloc); defer p.deinit(); while (true) { const datum = p.run(reader) catch { @@ -30,16 +34,17 @@ pub fn main() !u8 { std.debug.print(format, .{ err, pos, unread }); return 1; }; - if (datum.eq(zisp.value.eof)) { + if (datum.eq(value.eof)) { return 0; } try writer.writeAll("0x"); try writer.printInt(datum.bits, 16, .lower, .{}); try writer.writeAll(": "); - try zisp.io.print(writer, datum); + try io.print(writer, datum); try writer.writeAll("\n"); try writer.flush(); - if (datum.isList()) try zisp.value.list.free(datum); + // To test list array free / reuse: + if (datum.isList()) try value.list.free(p.alloc, p.list_pool, datum); } } diff --git a/src/zisp/gc/ListPool.zig b/src/zisp/gc/ListPool.zig index a843ae5..0735582 100644 --- a/src/zisp/gc/ListPool.zig +++ b/src/zisp/gc/ListPool.zig @@ -21,11 +21,8 @@ const SegStack = seg_stack.SegStack; const Self = @This(); -/// How many Value elements fit in a block. A good value should be 512, since -/// each Value is 8 bytes: 512 * 8 = 4 KiB -const block_value_cap = 512; - -const Block = [block_value_cap]Value; +// 4 KiB blocks fit 512 Value elements, which should be good. +const Block = [4096 / @sizeOf(Value)]Value; alloc: Alloc, @@ -65,6 +62,10 @@ fn newBlock(self: *Self) !void { self.current_index = 0; } +fn curBlockPtr(self: *Self) [*]Value { + return @ptrCast(&self.current_block[self.current_index]); +} + fn popFree(self: *Self, len: u3) ?[*]Value { return self.free_lists[len - 1].pop(self.alloc); } @@ -78,17 +79,27 @@ pub fn allocVals(self: *Self, len: u3) ![*]Value { if (self.popFree(len)) |ptr| return ptr; - if (len > block_value_cap - self.current_index) { + if (len > self.current_block.len - self.current_index) { try self.newBlock(); } defer self.current_index += len; - return @ptrCast(&self.current_block[self.current_index]); + return self.curBlockPtr(); } pub fn freeVals(self: *Self, len: u3, ptr: [*]Value) !void { std.debug.assert(len != 0); + // Is it simply the last allocation? If so, just undo it. + if (self.current_index >= len) { + const ptr_val = @intFromPtr(ptr); + const last_ptr_val = @intFromPtr(self.curBlockPtr() - len); + if (ptr_val == last_ptr_val) { + self.current_index -= len; + return; + } + } + try self.pushFree(len, ptr); } diff --git a/src/zisp/value.zig b/src/zisp/value.zig index 4ce6cd2..2ae0524 100644 --- a/src/zisp/value.zig +++ b/src/zisp/value.zig @@ -269,16 +269,16 @@ pub const Value = packed union { } /// Checks for a pointer and returns the value and tag separately, or null - /// if this isn't a pointer or null. Could be useful for a dispatch table. - pub fn getPtrAny(v: Value) ?struct { Zptr, HeapType } { + /// if this isn't a pointer at all. Could be useful for a dispatch table. + /// Note that unlike getPtr(), this can actually return a null pointer as + /// such, not conflating it with the "not a heap pointer" case. + pub fn getPtrAny(v: Value) ?struct { ?Zptr, HeapType } { const hi16_bits: u16 = @intCast(v.bits >> 48); if (hi16_bits != hi16_tag_ptr) return null; - const ptr_val: u48 = @intCast(v.bits << 20 >> 16); - if (ptr_val == 0) return null; - - const ht_val: u4 = @intCast(v.bits << 16 >> 60); - return .{ @ptrFromInt(ptr_val), @enumFromInt(ht_val) }; + const ht: u4 = @truncate(hi16_bits); + const pval: u48 = @intCast(v.bits << 20 >> 16); + return .{ @ptrFromInt(pval), @enumFromInt(ht) }; } /// Checks if the value is a list pointer. diff --git a/src/zisp/value/list.zig b/src/zisp/value/list.zig index 52c665e..a78d274 100644 --- a/src/zisp/value/list.zig +++ b/src/zisp/value/list.zig @@ -38,9 +38,15 @@ pub fn new(alloc: Alloc, pool: ?*ListPool, vals: []const Value) !Value { return .{ .list = .{ .len_tagged_ptr = len_tagged_ptr } }; } -// TODO: this is just a test -pub fn free(list: Value) !void { - try gc.mainListPool().freeList(list); +pub fn free(alloc: Alloc, pool: ?*ListPool, list: Value) !void { + const len = getLenTag(list); + const ptr = getValPtr(list); + if (len == 0 or pool == null) { + const full_len = findFullLen(list); + alloc.free(ptr[0..full_len]); + } else { + try pool.?.freeVals(len, ptr); + } } pub fn getLenTag(v: Value) u3 { @@ -51,19 +57,26 @@ pub fn getValPtr(v: Value) [*]Value { return @ptrFromInt(v.bits & 0x0000fffffffffff8); } +pub fn findFullLen(v: Value) usize { + std.debug.assert(getLenTag(v) == 0); + const ptr: [*]u64 = @ptrCast(getValPtr(v)); + var i: usize = 8; + while (true) : (i += 8) { + const vals: @Vector(8, u64) = (ptr + i)[0..8].*; + const mask: @Vector(8, u64) = @splat(value.none.bits); + const results: u8 = @bitCast(vals == mask); + if (results != 0) return i + @clz(results); + } +} + // Zisp API pub fn pred(v: Value) Value { return value.boole.pack(check(v)); } -pub fn getLen(v: Value) Value { +pub fn getLength(v: Value) Value { assert(v); - var len = getLenTag(v); - if (len == 0) { - const ptr = getValPtr(v); - len = 8; - while (ptr[len].bits != value.none.bits) len += 1; - } + const len = findFullLen(v); return value.fixnum.pack(@intCast(len)); } -- cgit v1.2.3