All MicroEvals
const mem = @import("mem.zig"); const addOv = mem.addOv; con...
Create MicroEval
Header image for const mem = @import("mem.zig");
const addOv = mem.addOv;
con...

const mem = @import("mem.zig"); const addOv = mem.addOv; con...

Prompt

const mem = @import("mem.zig"); const addOv = mem.addOv; const mulOv = mem.mulOv; pub inline fn allocAlignForward(addr: usize, alignment: usize) ?usize { if (alignment == 0 or alignment & (alignment - 1) != 0) return null; const end = addOv(usize, addr, alignment - 1) orelse return null; return end & ~(alignment - 1); } pub const Allocator = struct { ptr: *anyopaque, vtable: *const VTable, pub const Error = error{OutOfMemory}; // Win64-only design: no `remap` (Windows has no mremap, so every impl could // only answer "same pointer or null" β€” which is exactly `resize`) and no // `ret_addr` plumbing (no debug allocator exists to consume it). pub const VTable = struct { alloc: *const fn (ctx: *anyopaque, len: usize, alignment: usize) ?[*]u8, resize: *const fn (ctx: *anyopaque, memory: []u8, alignment: usize, new_len: usize) bool, free: *const fn (ctx: *anyopaque, memory: []u8, alignment: usize) void, }; fn byteLen(comptime T: type, n: usize) ?usize { return mulOv(usize, @sizeOf(T), n); } pub inline fn rawAlloc(self: Allocator, len: usize, alignment: usize) ?[*]u8 { if (alignment == 0 or alignment & (alignment - 1) != 0) return null; return self.vtable.alloc(self.ptr, len, alignment); } pub inline fn rawResize(self: Allocator, memory: []u8, alignment: usize, new_len: usize) bool { return self.vtable.resize(self.ptr, memory, alignment, new_len); } pub inline fn rawFree(self: Allocator, memory: []u8, alignment: usize) void { return self.vtable.free(self.ptr, memory, alignment); } pub fn alloc(self: Allocator, comptime T: type, n: usize) Error![]T { if (n == 0 or @sizeOf(T) == 0) { const dangling: [*]align(@alignOf(T)) T = @ptrFromInt(@alignOf(T)); return dangling[0..0]; } const len = byteLen(T, n) orelse return error.OutOfMemory; const raw = self.rawAlloc(len, @alignOf(T)) orelse return error.OutOfMemory; const tptr: [*]T = @ptrCast(@alignCast(raw)); return tptr[0..n]; } pub fn allocSentinel(self: Allocator, comptime T: type, n: usize, comptime sentinel: T) Error![:sentinel]T { if (n == ~@as(usize, 0)) return error.OutOfMemory; const buf = try self.alloc(T, n + 1); buf[n] = sentinel; return buf[0..n :sentinel]; } pub fn dupe(self: Allocator, comptime T: type, m: []const T) Error![]T { const buf = try self.alloc(T, m.len); @memcpy(buf, m); return buf; } pub fn create(self: Allocator, comptime T: type) Error!*T { const s = try self.alloc(T, 1); return &s[0]; } pub fn destroy(self: Allocator, ptr: anytype) void { const T = @typeInfo(@TypeOf(ptr)).pointer.child; const p: [*]T = @ptrCast(ptr); self.free(p[0..1]); } pub fn free(self: Allocator, memory: anytype) void { const info = @typeInfo(@TypeOf(memory)).pointer; const T = info.child; // A sentinel slice owns one element past len (see allocSentinel); // under-reporting it would free into the wrong smp size class. const sentinel_bytes: usize = if (info.sentinel_ptr != null) @sizeOf(T) else 0; const data_bytes = mulOv(usize, memory.len, @sizeOf(T)) orelse unreachable; const len = addOv(usize, data_bytes, sentinel_bytes) orelse unreachable; if (len == 0) return; const bytes: [*]u8 = @ptrCast(@constCast(memory.ptr)); // 0xAA-poison in Debug; writing undefined is elided in release modes. @memset(bytes[0..len], undefined); self.rawFree(bytes[0..len], @alignOf(T)); } /// Byte-level resize shared by every Vec(T) instantiation: one copy of the /// resize-else-alloc+copy+free path instead of a monomorphized realloc per /// element type. Handles grow and shrink. Caller guarantees new_len > 0. pub noinline fn resizeBytes(self: Allocator, old_ptr: [*]u8, old_len: usize, new_len: usize, alignment: usize) Error![*]u8 { if (old_len == 0) return self.rawAlloc(new_len, alignment) orelse error.OutOfMemory; const old = old_ptr[0..old_len]; if (self.rawResize(old, alignment, new_len)) return old_ptr; const raw = self.rawAlloc(new_len, alignment) orelse return error.OutOfMemory; const copy = @min(old_len, new_len); @memcpy(raw[0..copy], old[0..copy]); @memset(old, undefined); self.rawFree(old, alignment); return raw; } }; /// Owned bytes whose logical length may be smaller than the allocation passed to /// `Allocator.free`. Keeping both values avoids a shrink-copy when an allocator's /// deallocation contract derives its size class from the slice length. pub const OwnedBuffer = struct { allocator: Allocator, storage: []u8, len: usize, pub fn init(allocator: Allocator, storage: []u8, len: usize) OwnedBuffer { if (len > storage.len) unreachable; return .{ .allocator = allocator, .storage = storage, .len = len }; } pub inline fn bytes(self: *const OwnedBuffer) []const u8 { return self.storage[0..self.len]; } pub inline fn capacity(self: *const OwnedBuffer) usize { return self.storage.len; } pub fn deinit(self: *OwnedBuffer) void { const storage = self.storage; self.storage = storage.ptr[0..0]; self.len = 0; self.allocator.free(storage); } }; pub const page_allocator = @import("alloc_page.zig").page_allocator; pub const ArenaAllocator = @import("alloc_arena.zig").ArenaAllocator; pub const smp_allocator = @import("alloc_smp.zig").smp_allocator; pub const Vec = @import("alloc_vec.zig").Vec; Review the above. fully rewrite a better version of it. still full hand roll. looking for LOC reduction or perf improvement. windows only.