diff options
| -rw-r--r-- | src/zisp/lib/seg_stack.zig | 11 | ||||
| -rw-r--r-- | src/zisp/value/array.zig | 14 | ||||
| -rw-r--r-- | src/zisp/value/fixnum.zig | 31 |
3 files changed, 22 insertions, 34 deletions
diff --git a/src/zisp/lib/seg_stack.zig b/src/zisp/lib/seg_stack.zig index 0867892..d2c6aaa 100644 --- a/src/zisp/lib/seg_stack.zig +++ b/src/zisp/lib/seg_stack.zig @@ -5,8 +5,13 @@ const std = @import("std"); const Alloc = std.mem.Allocator; /// Segmented linked list backed stack -pub fn SegStack(T: type, seg_max_bytes: usize) type { - const seg_size: usize = (seg_max_bytes - @sizeOf(usize)) / @sizeOf(T); +pub fn SegStack(T: type, seg_max_bytes: comptime_int) type { + + // Each Node has a pointer (= usize) and the element array; calculate the + // correct segment size (as in element count) based on that. + const seg_size = (seg_max_bytes - @sizeOf(usize)) / @sizeOf(T); + + const IdxType = std.math.IntFittingRange(seg_size); comptime { if (seg_size < 4) { @@ -31,7 +36,7 @@ pub fn SegStack(T: type, seg_max_bytes: usize) type { const Self = @This(); head: *Node, - idx: usize = 0, + idx: IdxType = 0, // To prevent "thrashing" we don't immediately deallocate the current // node when it's emptied but rather save it aside. diff --git a/src/zisp/value/array.zig b/src/zisp/value/array.zig index 34e75b9..cdc5f75 100644 --- a/src/zisp/value/array.zig +++ b/src/zisp/value/array.zig @@ -50,13 +50,13 @@ const Value = value.Value; /// Other remaining bits provide information about element type and size. pub const ArrayPtr = *align(@alignOf(value.Zptr)) ArrayHeader; -// Important: We may use a hack where lists, residing in their own heap region, -// can be turned into value arrays by transforming their first element into an -// ArrayHeader. However, it might simplify the GC algorithm if the entirety of -// that heap region can be treated as Value slots. If we ensure that ArrayHead -// never looks like a Value with a pointer payload, this will be safe; as such, -// we ensure that it has some of the "exponent" bits unset, making it always -// look like a regular Double value. This is what "_DONTUSE" is for. +// Important: We may or may not use a hack one day in which an algorithm, like +// for GC purposes, scans through certain memory regions looking for NaN-packed +// pointers conservatively. If we ever decide to do this, there's a chance it +// may come across ArrayHeader instances and treats them like a Value. We can +// ensure that, even then, an ArrayHeader can't be confused for a NaN-packed +// pointer, by ensuring that some of the high bits are unset, so it has the +// format of a regular Double. This is what "_DONTUSE" is for. pub const ArrayHeader = packed struct(u64) { len_or_ptr: u48, is_slice: bool = false, diff --git a/src/zisp/value/fixnum.zig b/src/zisp/value/fixnum.zig index 3bd6112..65207a6 100644 --- a/src/zisp/value/fixnum.zig +++ b/src/zisp/value/fixnum.zig @@ -34,41 +34,24 @@ fn assertValidRange(int: i64) void { } } -const positive_mask: u64 = 0xfff7ffffffffffff; - -fn packNegative(int: i64) Value { - return @bitCast(int); -} - -fn unpackNegative(v: Value) i64 { - return @bitCast(v); -} - -fn packPositive(int: i64) Value { - const uint: u64 = @bitCast(int); - return @bitCast(uint ^ positive_mask); -} - -fn unpackPositive(v: Value) i64 { - const uint: u64 = @bitCast(v); - return @bitCast(uint ^ positive_mask); -} +const pos_mask: u64 = 0xfff7ffffffffffff; pub fn pack(int: i64) Value { assertValidRange(int); if (int < 0) { - return packNegative(int); + return @bitCast(int); } else { - return packPositive(int); + const uint: u64 = @bitCast(int); + return @bitCast(uint ^ pos_mask); } } pub fn unpack(v: Value) i64 { assert(v); - if (v.fixnum.negative) { - return unpackNegative(v); + if (v.fixnum.sign) { + return @bitCast(v.bits); } else { - return unpackPositive(v); + return @bitCast(v.bits ^ pos_mask); } } |
