fix(mir): PHI検証panic修正 - update_cfg()を検証前に呼び出し
A案実装: debug_verify_phi_inputs呼び出し前にCFG predecessorを更新
修正箇所(7箇所):
- src/mir/builder/phi.rs:50, 73, 132, 143
- src/mir/builder/ops.rs:273, 328, 351
根本原因:
- Branch/Jump命令でsuccessorは即座に更新
- predecessorはupdate_cfg()で遅延再構築
- PHI検証が先に実行されてpredecessor未更新でpanic
解決策:
- 各debug_verify_phi_inputs呼び出し前に
if let Some(func) = self.current_function.as_mut() {
func.update_cfg();
}
を挿入してCFGを同期
影響: if/else文、論理演算子(&&/||)のPHI生成が正常動作
This commit is contained in:
@ -6,31 +6,31 @@
|
||||
static box GcBox {
|
||||
// Return JSON string with counters {safepoints, barrier_reads, barrier_writes}
|
||||
stats() {
|
||||
return call("env.gc.stats/0")
|
||||
return gc.stats()
|
||||
}
|
||||
|
||||
// Return total roots count (host handles + modules), best‑effort integer
|
||||
roots_snapshot() {
|
||||
return call("env.gc.roots_snapshot/0")
|
||||
return gc.roots_snapshot()
|
||||
}
|
||||
|
||||
// Request collection (no‑op until host supports it)
|
||||
collect() {
|
||||
// Host may ignore; keep Fail‑Fast if extern missing
|
||||
call("env.gc.collect/0")
|
||||
gc.collect()
|
||||
}
|
||||
|
||||
// Optional lifecycle hooks (no‑op unless host implements)
|
||||
start() { call("env.gc.start/0"); }
|
||||
stop() { call("env.gc.stop/0"); }
|
||||
start() { gc.start(); }
|
||||
stop() { gc.stop(); }
|
||||
|
||||
// Example (dev): a tiny cadence policy, OFF by default.
|
||||
// Enable with: HAKO_GC_POLICY_TICK=1 (docs only; call manually from scripts)
|
||||
policy_tick() {
|
||||
if (call("env.local.get/1", "HAKO_GC_POLICY_TICK") == "1") {
|
||||
if (env.get("HAKO_GC_POLICY_TICK") == "1") {
|
||||
// Read metrics and print a compact line for observation
|
||||
local s = me.stats()
|
||||
call("env.console.log/1", "[GcBox] stats=" + s)
|
||||
console.log("[GcBox] stats=" + s)
|
||||
// Example threshold (no-op unless host implements collect):
|
||||
// me.collect()
|
||||
}
|
||||
@ -41,12 +41,12 @@ static box GcBox {
|
||||
// HAKO_GC_POLICY_FORCE=1 → call collect() each tick (may be no-op; guard expected)
|
||||
// HAKO_GC_POLICY_EVERY_N=K → best-effort modulus trigger (tick_count % K == 0)
|
||||
tick_with_policy(tick_count) {
|
||||
local log = call("env.local.get/1", "HAKO_GC_POLICY_LOG")
|
||||
local every = call("env.local.get/1", "HAKO_GC_POLICY_EVERY_N")
|
||||
local force = call("env.local.get/1", "HAKO_GC_POLICY_FORCE")
|
||||
local log = env.get("HAKO_GC_POLICY_LOG")
|
||||
local every = env.get("HAKO_GC_POLICY_EVERY_N")
|
||||
local force = env.get("HAKO_GC_POLICY_FORCE")
|
||||
|
||||
if (log == "1") {
|
||||
call("env.console.log/1", "[GcBox] stats=" + me.stats())
|
||||
console.log("[GcBox] stats=" + me.stats())
|
||||
}
|
||||
if (force == "1") {
|
||||
// Gate: host may not implement collect() yet
|
||||
|
||||
@ -11,44 +11,44 @@ static box ArcBox {
|
||||
_key(ptr) { return "ARC_" + ("" + ptr) }
|
||||
|
||||
_debug_on() {
|
||||
local d = call("env.local.get/1", "HAKO_DEBUG_ARC")
|
||||
if d == null || d == "" { d = call("env.local.get/1", "NYASH_DEBUG_ARC") }
|
||||
local d = env.get("HAKO_DEBUG_ARC")
|
||||
if d == null || d == "" { d = env.get("NYASH_DEBUG_ARC") }
|
||||
return d == "1"
|
||||
}
|
||||
|
||||
_log(msg) { if me._debug_on() { call("env.console.log/1", "[ArcBox] " + msg) } }
|
||||
_log(msg) { if me._debug_on() { console.log("[ArcBox] " + msg) } }
|
||||
|
||||
// Read current count (>=0) or -1 if unset/unknown)
|
||||
_get_count(ptr) { return call("env.arc.count/1", ptr) }
|
||||
_get_count(ptr) { return arc.count(ptr) }
|
||||
|
||||
// Create a new ARC handle with count=1. Fail if already exists.
|
||||
arc_birth(ptr) {
|
||||
local c = me._get_count(ptr)
|
||||
if c >= 0 { call("env.console.error/1", "[arc/already_exists]") return -1 }
|
||||
call("env.arc.birth/1", ptr)
|
||||
if c >= 0 { console.error("[arc/already_exists]") return -1 }
|
||||
arc.birth(ptr)
|
||||
me._log("birth ptr=" + ("" + ptr) + " -> 1")
|
||||
return 1
|
||||
}
|
||||
|
||||
// Increment; Fail if unknown.
|
||||
arc_retain(ptr) {
|
||||
local c = call("env.arc.retain/1", ptr)
|
||||
if c < 0 { call("env.console.error/1", "[arc/unknown]") return -1 }
|
||||
local c = arc.retain(ptr)
|
||||
if c < 0 { console.error("[arc/unknown]") return -1 }
|
||||
me._log("retain ptr=" + ("" + ptr) + " -> " + StringHelpers.int_to_str(c))
|
||||
return c
|
||||
}
|
||||
|
||||
// Decrement; Fail on unknown or underflow. When reaches 0, optionally free via env.mem.free/1
|
||||
arc_release(ptr) {
|
||||
local n = call("env.arc.release/1", ptr)
|
||||
local n = arc.release(ptr)
|
||||
if n < 0 { return -1 }
|
||||
me._log("release ptr=" + ("" + ptr) + " -> " + StringHelpers.int_to_str(n))
|
||||
if n == 0 {
|
||||
local fz = call("env.local.get/1", "HAKO_ARC_FREE_ON_ZERO")
|
||||
if fz == null || fz == "" { fz = call("env.local.get/1", "NYASH_ARC_FREE_ON_ZERO") }
|
||||
local fz = env.get("HAKO_ARC_FREE_ON_ZERO")
|
||||
if fz == null || fz == "" { fz = env.get("NYASH_ARC_FREE_ON_ZERO") }
|
||||
if fz == "1" {
|
||||
// Best-effort free; ignore missing handler
|
||||
call("env.mem.free/1", ptr)
|
||||
mem.free(ptr)
|
||||
}
|
||||
}
|
||||
return n
|
||||
|
||||
@ -9,18 +9,18 @@ static box RefCellBox {
|
||||
_key(ptr) { return "ref:" + ("" + ptr) }
|
||||
|
||||
_debug_on() {
|
||||
local d = call("env.local.get/1", "HAKO_DEBUG_REFCELL")
|
||||
if d == null || d == "" { d = call("env.local.get/1", "NYASH_DEBUG_REFCELL") }
|
||||
local d = env.get("HAKO_DEBUG_REFCELL")
|
||||
if d == null || d == "" { d = env.get("NYASH_DEBUG_REFCELL") }
|
||||
return d == "1"
|
||||
}
|
||||
_log(msg) { if me._debug_on() { call("env.console.log/1", "[RefCellBox] " + msg) } }
|
||||
_log(msg) { if me._debug_on() { console.log("[RefCellBox] " + msg) } }
|
||||
|
||||
_get(ptr) {
|
||||
local s = call("env.local.get/1", me._key(ptr))
|
||||
local s = env.get(me._key(ptr))
|
||||
if s == null || s == "" { return 0 }
|
||||
return StringHelpers.to_i64(s)
|
||||
}
|
||||
_set(ptr, n) { call("env.local.set/2", me._key(ptr), StringHelpers.int_to_str(n)) }
|
||||
_set(ptr, n) { env.set(me._key(ptr), StringHelpers.int_to_str(n)) }
|
||||
|
||||
// Initialize state to 0 (idempotent)
|
||||
init(ptr) { me._set(ptr, 0) return 0 }
|
||||
@ -28,7 +28,7 @@ static box RefCellBox {
|
||||
// Shared borrow: allow when state >= 0; increments shared counter.
|
||||
try_borrow(ptr) {
|
||||
local st = me._get(ptr)
|
||||
if st < 0 { call("env.console.error/1", "[refcell/conflict_shared]") return -1 }
|
||||
if st < 0 { console.error("[refcell/conflict_shared]") return -1 }
|
||||
me._set(ptr, st + 1)
|
||||
me._log("borrow ptr=" + ("" + ptr) + " -> " + StringHelpers.int_to_str(st + 1))
|
||||
return 1
|
||||
@ -37,7 +37,7 @@ static box RefCellBox {
|
||||
// Mutable borrow: allow only when state == 0.
|
||||
try_borrow_mut(ptr) {
|
||||
local st = me._get(ptr)
|
||||
if st != 0 { call("env.console.error/1", "[refcell/conflict_mut]") return -1 }
|
||||
if st != 0 { console.error("[refcell/conflict_mut]") return -1 }
|
||||
me._set(ptr, -1)
|
||||
me._log("borrow_mut ptr=" + ("" + ptr) + " -> -1")
|
||||
return 1
|
||||
@ -46,7 +46,7 @@ static box RefCellBox {
|
||||
// Release one shared borrow; Fail if not in shared state
|
||||
release_shared(ptr) {
|
||||
local st = me._get(ptr)
|
||||
if st <= 0 { call("env.console.error/1", "[refcell/release_shared_invalid]") return -1 }
|
||||
if st <= 0 { console.error("[refcell/release_shared_invalid]") return -1 }
|
||||
me._set(ptr, st - 1)
|
||||
me._log("release_shared ptr=" + ("" + ptr) + " -> " + StringHelpers.int_to_str(st - 1))
|
||||
return st - 1
|
||||
@ -55,7 +55,7 @@ static box RefCellBox {
|
||||
// Release mutable borrow; Fail if not in mut state
|
||||
release_mut(ptr) {
|
||||
local st = me._get(ptr)
|
||||
if st != -1 { call("env.console.error/1", "[refcell/release_mut_invalid]") return -1 }
|
||||
if st != -1 { console.error("[refcell/release_mut_invalid]") return -1 }
|
||||
me._set(ptr, 0)
|
||||
me._log("release_mut ptr=" + ("" + ptr) + " -> 0")
|
||||
return 0
|
||||
|
||||
@ -6,17 +6,17 @@ using "lang/src/shared/json/json_utils.hako" as JsonUtilsBox
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
|
||||
static box JsonShapeToMap {
|
||||
_empty(){ return map({ using_paths: new ArrayBox(), modules: new ArrayBox(), aliases: map({}), packages: map({}) }) }
|
||||
_empty(){ return { using_paths: new ArrayBox(), modules: new ArrayBox(), aliases: {}, packages: {} } }
|
||||
|
||||
_parse_array_of_strings(arr_json){
|
||||
local out = new ArrayBox()
|
||||
if !arr_json || arr_json.size() < 2 { return out }
|
||||
if !arr_json || arr_json.length() < 2 { return out }
|
||||
local parts = JsonUtilsBox.split_top_level(arr_json)
|
||||
local i = 0
|
||||
loop(i < parts.size()){
|
||||
loop(i < parts.length()){
|
||||
local v = StringHelpers.trim(parts.get(i))
|
||||
if v.size() >= 2 && v.substring(0,1) == "\"" && v.substring(v.size()-1, v.size()) == "\"" {
|
||||
out.push(JsonUtilsBox.unescape_string(v.substring(1, v.size()-1)))
|
||||
if v.length() >= 2 && v.substring(0,1) == "\"" && v.substring(v.length()-1, v.length()) == "\"" {
|
||||
out.push(JsonUtilsBox.unescape_string(v.substring(1, v.length()-1)))
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
@ -26,8 +26,8 @@ static box JsonShapeToMap {
|
||||
_split_object_pairs(obj_json){
|
||||
// Like split_top_level for arrays, but for object key:value pairs inside {...}
|
||||
local out = new ArrayBox()
|
||||
if !obj_json || obj_json.size() < 2 { return out }
|
||||
local n = obj_json.size()
|
||||
if !obj_json || obj_json.length() < 2 { return out }
|
||||
local n = obj_json.length()
|
||||
local i = 1
|
||||
local start = 1
|
||||
local depth = 0
|
||||
@ -56,12 +56,12 @@ static box JsonShapeToMap {
|
||||
_read_key_from_pair(pair_json){
|
||||
// pair_json: '"key" : value'
|
||||
local s = StringHelpers.trim(pair_json)
|
||||
if s.size() < 3 || s.substring(0,1) != "\"" { return null }
|
||||
if s.length() < 3 || s.substring(0,1) != "\"" { return null }
|
||||
local end = JsonUtilsBox.skip_string(s, 0)
|
||||
local raw = s.substring(0, end)
|
||||
// raw like "\"key\"@pos" from read_string; we used skip_string, so raw lacks marker
|
||||
// Remove quotes
|
||||
local key = JsonUtilsBox.unescape_string(raw.substring(1, raw.size()-1))
|
||||
local key = JsonUtilsBox.unescape_string(raw.substring(1, raw.length()-1))
|
||||
return key
|
||||
}
|
||||
|
||||
@ -80,15 +80,15 @@ static box JsonShapeToMap {
|
||||
|
||||
_parse_modules(mods_json){
|
||||
local out = new ArrayBox()
|
||||
if !mods_json || mods_json.size() < 2 { return out }
|
||||
if !mods_json || mods_json.length() < 2 { return out }
|
||||
local parts = JsonUtilsBox.split_top_level(mods_json)
|
||||
local i = 0
|
||||
loop(i < parts.size()){
|
||||
loop(i < parts.length()){
|
||||
local obj = StringHelpers.trim(parts.get(i))
|
||||
if obj.size() >= 2 && obj.substring(0,1) == "{" {
|
||||
if obj.length() >= 2 && obj.substring(0,1) == "{" {
|
||||
local ns = JsonUtilsBox.extract_string_value(obj, "ns", "")
|
||||
local path = JsonUtilsBox.extract_string_value(obj, "path", "")
|
||||
out.push(map({ ns: ns, path: path }))
|
||||
out.push({ ns: ns, path: path })
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
@ -96,18 +96,18 @@ static box JsonShapeToMap {
|
||||
}
|
||||
|
||||
_parse_aliases(obj_json){
|
||||
local out = map({})
|
||||
if !obj_json || obj_json.size() < 2 { return out }
|
||||
local out = {}
|
||||
if !obj_json || obj_json.length() < 2 { return out }
|
||||
local pairs = me._split_object_pairs(obj_json)
|
||||
local i = 0
|
||||
loop(i < pairs.size()){
|
||||
loop(i < pairs.length()){
|
||||
local p = pairs.get(i)
|
||||
local key = me._read_key_from_pair(p)
|
||||
local val_raw = me._read_value_from_pair(p)
|
||||
if key != null && val_raw != null {
|
||||
local v = StringHelpers.trim(val_raw)
|
||||
if v.size() >= 2 && v.substring(0,1) == "\"" && v.substring(v.size()-1, v.size()) == "\"" {
|
||||
out.set(key, JsonUtilsBox.unescape_string(v.substring(1, v.size()-1)))
|
||||
if v.length() >= 2 && v.substring(0,1) == "\"" && v.substring(v.length()-1, v.length()) == "\"" {
|
||||
out.set(key, JsonUtilsBox.unescape_string(v.substring(1, v.length()-1)))
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
@ -116,11 +116,11 @@ static box JsonShapeToMap {
|
||||
}
|
||||
|
||||
_parse_packages(obj_json){
|
||||
local out = map({})
|
||||
if !obj_json || obj_json.size() < 2 { return out }
|
||||
local out = {}
|
||||
if !obj_json || obj_json.length() < 2 { return out }
|
||||
local pairs = me._split_object_pairs(obj_json)
|
||||
local i = 0
|
||||
loop(i < pairs.size()){
|
||||
loop(i < pairs.length()){
|
||||
local p = pairs.get(i)
|
||||
local key = me._read_key_from_pair(p)
|
||||
local val_raw = me._read_value_from_pair(p)
|
||||
@ -128,7 +128,7 @@ static box JsonShapeToMap {
|
||||
local kind = JsonUtilsBox.extract_string_value(val_raw, "kind", "")
|
||||
local path = JsonUtilsBox.extract_string_value(val_raw, "path", "")
|
||||
local main = JsonUtilsBox.extract_string_value(val_raw, "main", "")
|
||||
out.set(key, map({ kind: kind, path: path, main: main }))
|
||||
out.set(key, { kind: kind, path: path, main: main })
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
@ -148,6 +148,6 @@ static box JsonShapeToMap {
|
||||
local modules = me._parse_modules(mods_arr)
|
||||
local aliases = me._parse_aliases(aliases_obj)
|
||||
local packages = me._parse_packages(packages_obj)
|
||||
return map({ using_paths: using_paths, modules: modules, aliases: aliases, packages: packages })
|
||||
return { using_paths: using_paths, modules: modules, aliases: aliases, packages: packages }
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,13 +6,13 @@ static box UsingResolver {
|
||||
// Shape: { using_paths: [], modules: [], aliases: {}, packages: {}, policy: {} }
|
||||
// Behavior-invariant: no I/O, no host-slot dependence.
|
||||
resolve(_token){
|
||||
return map({
|
||||
return {
|
||||
using_paths: new ArrayBox(),
|
||||
modules: new ArrayBox(),
|
||||
aliases: map({}),
|
||||
packages: map({}),
|
||||
policy: map({})
|
||||
});
|
||||
aliases: {},
|
||||
packages: {},
|
||||
policy: {}
|
||||
};
|
||||
}
|
||||
|
||||
// stats/1 — Return minimal JSON counts (lang-side observability; behavior-invariant)
|
||||
|
||||
Reference in New Issue
Block a user