haku2: add stats + fix crash w uninit vm
This commit is contained in:
parent
e667c6336a
commit
00a48527ca
12 changed files with 88 additions and 71 deletions
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const log = std.log.scoped(.bytecode);
|
||||
|
||||
/// NOTE: This must be mirrored in bytecode.rs.
|
||||
pub const Opcode = enum(u8) {
|
||||
|
@ -70,6 +71,8 @@ pub const Defs = struct {
|
|||
.num_tags = mem.count(u8, tags_string, "\n"),
|
||||
};
|
||||
|
||||
log.debug("parsed defs {*} tags {s}: {}", .{ defs_string, tags_string, d });
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@ const value = @import("value.zig");
|
|||
const Vm = @import("vm.zig");
|
||||
const log = @import("log.zig");
|
||||
|
||||
const debug_logs = true;
|
||||
|
||||
pub const allocator =
|
||||
if (builtin.cpu.arch == .wasm32)
|
||||
std.heap.wasm_allocator
|
||||
|
@ -19,10 +17,14 @@ pub const allocator =
|
|||
@import("allocator.zig").hostAllocator;
|
||||
|
||||
pub const std_options: std.Options = .{
|
||||
.log_level = if (debug_logs) .debug else .info,
|
||||
.log_level = .debug,
|
||||
.logFn = log.logFn,
|
||||
};
|
||||
|
||||
pub fn enableLogScope(scope: @TypeOf(.enum_literal)) bool {
|
||||
if (scope == .vm) return false else return true;
|
||||
}
|
||||
|
||||
// Allocator
|
||||
|
||||
export fn haku2_alloc(size: usize, alignment: usize) ?[*]u8 {
|
||||
|
@ -47,6 +49,10 @@ export fn haku2_scratch_reset(scratch: *Scratch) void {
|
|||
scratch.fixedBuffer = std.heap.FixedBufferAllocator.init(scratch.buffer);
|
||||
}
|
||||
|
||||
export fn haku2_scratch_used(scratch: *const Scratch) usize {
|
||||
return scratch.fixedBuffer.end_index;
|
||||
}
|
||||
|
||||
// Limits
|
||||
|
||||
export fn haku2_limits_new() ?*Vm.Limits {
|
||||
|
@ -88,12 +94,9 @@ export fn haku2_defs_destroy(defs: *bytecode.Defs) void {
|
|||
|
||||
// VM
|
||||
|
||||
export fn haku2_vm_new(s: *Scratch, defs: *const bytecode.Defs, limits: *const Vm.Limits) ?*Vm {
|
||||
export fn haku2_vm_new() ?*Vm {
|
||||
const vm = allocator.create(Vm) catch return null;
|
||||
errdefer allocator.destroy(vm);
|
||||
|
||||
vm.* = Vm.init(s.allocator(), defs, limits) catch return null;
|
||||
|
||||
vm.* = .{};
|
||||
return vm;
|
||||
}
|
||||
|
||||
|
@ -101,8 +104,10 @@ export fn haku2_vm_destroy(vm: *Vm) void {
|
|||
allocator.destroy(vm);
|
||||
}
|
||||
|
||||
export fn haku2_vm_reset(vm: *Vm, fuel: u32) void {
|
||||
export fn haku2_vm_reset(vm: *Vm, s: *Scratch, defs: *const bytecode.Defs, limits: *const Vm.Limits, fuel: u32) bool {
|
||||
vm.* = Vm.init(s.allocator(), defs, limits) catch return false;
|
||||
vm.reset(fuel);
|
||||
return true;
|
||||
}
|
||||
|
||||
export fn haku2_vm_run_main(
|
||||
|
@ -160,6 +165,10 @@ export fn haku2_vm_run_dotter(
|
|||
return true;
|
||||
}
|
||||
|
||||
export fn haku2_vm_fuel(vm: *const Vm) usize {
|
||||
return vm.fuel;
|
||||
}
|
||||
|
||||
export fn haku2_vm_exception_len(vm: *const Vm) usize {
|
||||
if (vm.exception) |exn| {
|
||||
return exn.len;
|
||||
|
|
|
@ -134,9 +134,15 @@ extern "C" {
|
|||
) -> *mut DefsC;
|
||||
fn haku2_defs_destroy(defs: *mut DefsC);
|
||||
|
||||
fn haku2_vm_new(s: *mut ScratchC, defs: *const DefsC, limits: *const LimitsC) -> *mut VmC;
|
||||
fn haku2_vm_new() -> *mut VmC;
|
||||
fn haku2_vm_destroy(vm: *mut VmC);
|
||||
fn haku2_vm_reset(vm: *mut VmC, fuel: u32);
|
||||
fn haku2_vm_reset(
|
||||
vm: *mut VmC,
|
||||
s: *mut ScratchC,
|
||||
defs: *const DefsC,
|
||||
limits: *const LimitsC,
|
||||
fuel: u32,
|
||||
);
|
||||
fn haku2_vm_run_main(
|
||||
vm: *mut VmC,
|
||||
scratch: *mut ScratchC,
|
||||
|
@ -296,6 +302,7 @@ impl Code {
|
|||
pub struct Vm {
|
||||
scratch: Scratch,
|
||||
code: Code,
|
||||
limits: Limits,
|
||||
inner: VmInner,
|
||||
}
|
||||
|
||||
|
@ -318,15 +325,10 @@ pub struct Dotter {
|
|||
}
|
||||
|
||||
impl Vm {
|
||||
pub fn new(scratch: Scratch, code: Code, limits: &Limits) -> Self {
|
||||
let raw = NonNull::new(unsafe {
|
||||
haku2_vm_new(
|
||||
scratch.raw.as_ptr(),
|
||||
code.defs.raw.as_ptr(),
|
||||
limits.raw.as_ptr(),
|
||||
)
|
||||
})
|
||||
.expect("out of memory");
|
||||
pub fn new(scratch: Scratch, code: Code, limits: Limits) -> Self {
|
||||
// SAFETY: haku2_vm_new cannot fail.
|
||||
// Do note that this returns an uninitialized VM, which must be reset before use.
|
||||
let raw = NonNull::new(unsafe { haku2_vm_new() }).expect("out of memory");
|
||||
trace!("Vm::new({scratch:?}, {code:?}, {limits:?}) -> {raw:?}");
|
||||
Self {
|
||||
// SAFETY:
|
||||
|
@ -336,6 +338,7 @@ impl Vm {
|
|||
inner: VmInner { raw },
|
||||
scratch,
|
||||
code,
|
||||
limits,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,8 +349,15 @@ impl Vm {
|
|||
/// continuation being stack on top of the old one---at the expense of a stack slot.
|
||||
pub fn begin(&mut self, fuel: u32) -> Result<(), Exception> {
|
||||
trace!("Vm::begin({self:?}, {fuel})");
|
||||
self.scratch.reset();
|
||||
let ok = unsafe {
|
||||
haku2_vm_reset(self.inner.raw.as_ptr(), fuel);
|
||||
haku2_vm_reset(
|
||||
self.inner.raw.as_ptr(),
|
||||
self.scratch.raw.as_ptr(),
|
||||
self.code.defs.raw.as_ptr(),
|
||||
self.limits.raw.as_ptr(),
|
||||
fuel,
|
||||
);
|
||||
haku2_vm_run_main(
|
||||
self.inner.raw.as_ptr(),
|
||||
self.scratch.raw.as_ptr(),
|
||||
|
@ -422,6 +432,7 @@ impl Vm {
|
|||
mut scratch,
|
||||
code: _,
|
||||
inner: _,
|
||||
limits: _,
|
||||
} = self;
|
||||
scratch.reset();
|
||||
scratch
|
||||
|
|
|
@ -9,6 +9,8 @@ pub fn logFn(
|
|||
comptime fmt: []const u8,
|
||||
args: anytype,
|
||||
) void {
|
||||
if (!root.enableLogScope(scope)) return;
|
||||
|
||||
const stack_buf_size = 1024;
|
||||
var stack_buf: [stack_buf_size]u8 = undefined;
|
||||
var heap_buf: ?[]u8 = null;
|
||||
|
|
|
@ -54,6 +54,6 @@ fn renderRec(vm: *Vm, canvas: *Canvas, val: Value, depth: usize, max_depth: usiz
|
|||
}
|
||||
|
||||
pub fn render(vm: *Vm, canvas: *Canvas, max_depth: usize) !void {
|
||||
const val = vm.stack[vm.stack_top - 1];
|
||||
const val = vm.top();
|
||||
try renderRec(vm, canvas, val, 0, max_depth);
|
||||
}
|
||||
|
|
|
@ -780,7 +780,6 @@ fn fill(color: Rgba, shape: value.Shape) value.Ref {
|
|||
}
|
||||
|
||||
fn withDotter(cont: *const value.Closure, cx: Context) Vm.Error!value.Ref {
|
||||
log.debug("withDotter({})", .{cont});
|
||||
if (cont.param_count != 1) {
|
||||
return cx.vm.throw("function passed to withDotter must have a single parameter (\\d -> _), but it has {}", .{cont.param_count});
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ const Value = value.Value;
|
|||
|
||||
const Vm = @This();
|
||||
|
||||
stack: []Value,
|
||||
stack: []Value = &.{},
|
||||
stack_top: u32 = 0,
|
||||
call_stack: []CallFrame,
|
||||
call_stack: []CallFrame = &.{},
|
||||
call_stack_top: u32 = 0,
|
||||
defs: []Value,
|
||||
defs: []Value = &.{},
|
||||
fuel: u32 = 0, // NOTE: VM must be refueled via reset() before running code
|
||||
exception: ?Exception = null,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue