vm(hako): v1 dispatcher internal scan (opt-in), hook extern provider (flag), share block scan; add v1 phi adapter placeholder; runner: v1→hakovm primary with Core fallback; add canary for internal dispatcher

This commit is contained in:
nyash-codex
2025-11-03 23:27:36 +09:00
parent 06a729ff40
commit 3bda84b136
6 changed files with 103 additions and 91 deletions

View File

@ -4,6 +4,7 @@
using selfhost.shared.json.utils.json_frag as JsonFragBox
using selfhost.vm.helpers.mini_mir_v1_scan as MiniMirV1Scan
using selfhost.vm.hakorune-vm.extern_provider as HakoruneExternProviderBox
static box MirCallV1HandlerBox {
handle(seg, regs) {
@ -55,6 +56,24 @@ static box MirCallV1HandlerBox {
}
// Minimal externs
if arg0id == null { arg0id = -1 }
// Optional provider route (flagged)
if env.get("HAKO_V1_EXTERN_PROVIDER") == "1" {
if name == "env.get" {
// resolve key value (string) from regs when available and write dst
local dstp = JsonFragBox.get_int(seg, "dst")
local keyv = null; if arg0id >= 0 { keyv = regs.getField(""+arg0id) }
local out = HakoruneExternProviderBox.get("env.get", keyv)
if dstp != null {
if out == null { regs.setField(""+dstp, "0") } else { regs.setField(""+dstp, ""+out) }
}
return
}
if name == "env.console.log" || name == "nyash.console.log" || name == "print" {
local keyv = null; if arg0id >= 0 { keyv = regs.getField(""+arg0id) }
HakoruneExternProviderBox.get("env.console.log", keyv)
return
}
}
if name == "env.console.log" || name == "nyash.console.log" ||
name == "env.console.warn" || name == "nyash.console.warn" ||
name == "env.console.error" || name == "nyash.console.error" {

View File

@ -28,83 +28,7 @@ static box MirVmMin {
}
_d(msg, trace) { if trace == 1 { print(msg) } }
_handle_mir_call(seg, regs) {
// Support minimal externs/methods (i64 variants). Constructor is noop.
// v1: treat Constructor as noop and write dst=0 to keep SSA continuity
if seg.indexOf("\"type\":\"Constructor\"") >= 0 {
local d0 = JsonFragBox.get_int(seg, "dst"); if d0 != null { regs.setField("" + d0, "0") }
return
}
local name = MiniMirV1Scan.callee_name(seg)
local arg0id = MiniMirV1Scan.first_arg_register(seg)
if name == "" {
// Try Method callee
local mname = MiniMirV1Scan.method_name(seg)
if mname != "" {
// Optional: minimal stateful bridge for size/len/length/push
// Enabled by HAKO_VM_MIRCALL_SIZESTATE=1 (default OFF). When OFF, emit stub tag and dst=0.
local size_state = env.get("HAKO_VM_MIRCALL_SIZESTATE")
if size_state == null { size_state = "0" }
if ("" + size_state) != "1" {
local stub = env.get("HAKO_VM_MIRCALL_STUB"); if stub == null { stub = "1" }
if ("" + stub) == "1" { print("[vm/method/stub:" + mname + "]") }
local dst0 = JsonFragBox.get_int(seg, "dst"); if dst0 != null { regs.setField("" + dst0, "0") }
return
}
// Stateful branch
// Length counter: global or per-receiver depending on flag
local per_recv = env.get("HAKO_VM_MIRCALL_SIZESTATE_PER_RECV")
if per_recv == null { per_recv = "0" }
local key = "__vm_len"
if (""+per_recv) == "1" {
local rid = MiniMirV1Scan.receiver_id(seg)
if rid != null { key = "__vm_len:" + (""+rid) }
}
local cur_len_raw = regs.getField(key); if cur_len_raw == null { cur_len_raw = "0" }
local cur_len = JsonFragBox._str_to_int(cur_len_raw)
if mname == "push" {
cur_len = cur_len + 1
regs.setField(key, "" + cur_len)
// push returns void/0 in this minimal path
local d1 = JsonFragBox.get_int(seg, "dst"); if d1 != null { regs.setField("" + d1, "0") }
return
}
if mname == "len" || mname == "length" || mname == "size" {
local d2 = JsonFragBox.get_int(seg, "dst"); if d2 != null { regs.setField("" + d2, "" + cur_len) }
return
}
// Others: no-op but keep stub tag for observability
print("[vm/method/stub:" + mname + "]")
local d3 = JsonFragBox.get_int(seg, "dst"); if d3 != null { regs.setField("" + d3, "0") }
return
}
me._tprint("[ERROR] mir_call: missing callee")
return
}
if arg0id == null { arg0id = -1 }
// String console: env/nyash console log/warn/error — treat arg0 as string
if name == "env.console.log" || name == "nyash.console.log" ||
name == "env.console.warn" || name == "nyash.console.warn" ||
name == "env.console.error" || name == "nyash.console.error" {
local v = ""
if arg0id >= 0 {
local raw = regs.getField(""+arg0id)
v = "" + raw
}
print(v)
return
}
if name == "hako_console_log_i64" {
local v = 0
if arg0id >= 0 { v = me._load_reg(regs, arg0id) }
print(me._int_to_str(v))
return
}
if name == "hako_bench_noop_i64" || name == "hako_bench_use_value_i64" {
// no-op (observability only)
return
}
// Unknown extern: FailFast (emit once)
me._tprint("[ERROR] extern not supported: " + name)
MirCallV1HandlerBox.handle(seg, regs)
}
// Compatibility runner (prints and returns). Prefer run_min for quiet return-only.
run(mjson) { local v = me._run_min(mjson) print(me._int_to_str(v)) return v }

View File

@ -0,0 +1,14 @@
// v1_phi_adapter.hako — V1PhiAdapterBox
// Responsibility: adapt MIR JSON v1 PHI incoming lists to the format expected
// by existing PhiDecodeBox/PhiApplyBox if needed. Currently acts as a
// pass-through for pairs [value, bb]. Kept as a place-holder for future needs.
box V1PhiAdapterBox {
normalize_incomings_v1(incomings) {
// incomings: JSON-level array already decoded into [value,bb] pairs
// This adapter is a no-op placeholder; return as-is.
return incomings
}
}
static box V1PhiAdapterMain { method main(args) { return 0 } }