summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/zisp/lib/seg_stack.zig11
-rw-r--r--src/zisp/value/array.zig14
-rw-r--r--src/zisp/value/fixnum.zig31
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);
}
}