feat(phase21.5): MirBuilder optimization prep + crate EXE infrastructure
Phase 21.5 optimization readiness - C-level performance target: - MirBuilder: JsonFrag purify toggle (HAKO_MIR_BUILDER_JSONFRAG_PURIFY=1) - Normalizer: extended f64 canonicalization + dedupe improvements - loop_opts_adapter: JsonFrag path refinement for crate EXE compatibility Infrastructure improvements: - provider_registry: add diagnostics + ring-1 providers (array/console/map/path) - mir_interpreter: add normalization/purify feature gates - tools/selfhost_exe_stageb.sh: new end-to-end Stage-B→crate EXE pipeline - tools/perf/microbench.sh: performance measurement tooling Smoke tests (phase2100): - Extend timeout 15s→120s for heavy crate EXE builds - Add stageb_loop_jsonfrag_crate_exe_canary_vm.sh (target test) - Add s3_backend_selector_crate_exe_vm_parity_return42_canary_vm.sh Documentation: - ENV_VARS.md: add Phase 21.5 optimization toggles - README updates: clarify crate backend strategy - phase215-optimization.md: new optimization roadmap This commit sets the stage for Phase 21.5 critical optimization: achieving C-level performance to decide hakorune's future viability.
This commit is contained in:
@ -52,6 +52,18 @@ static box MirBuilderBox {
|
||||
local internal = env.get("HAKO_MIR_BUILDER_INTERNAL")
|
||||
local internal_on = (internal == null) || (("" + internal) == "1")
|
||||
if internal_on == 1 {
|
||||
// Dev-only: force loop JSONFrag minimal output (pre-optimization bring-up)
|
||||
// Guard: HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1
|
||||
{
|
||||
local f = env.get("HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG")
|
||||
if f != null && ("" + f) == "1" {
|
||||
local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[" +
|
||||
"{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":0}},{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":0}},{\"op\":\"compare\",\"operation\":\"<\",\"lhs\":1,\"rhs\":2,\"dst\":3},{\"op\":\"branch\",\"cond\":3,\"then\":1,\"else\":2}]}," +
|
||||
"{\"id\":1,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}," +
|
||||
"{\"id\":2,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}]}]}"
|
||||
return norm_if(mir)
|
||||
}
|
||||
}
|
||||
// Optional: registry-driven lowering (scaffold). When HAKO_MIR_BUILDER_REGISTRY=1,
|
||||
// iterate PatternRegistryBox.candidates() and dispatch by name.
|
||||
// NOTE: using/alias は prelude で解決される(位置に依存しない)。
|
||||
|
||||
@ -1,22 +1,12 @@
|
||||
# MirBuilder Internal Boxes — Minimal Shapes (Phase 20.34)
|
||||
MirBuilder Internals — Toggle Aggregation
|
||||
|
||||
Responsibility
|
||||
- Provide small, readable boxes that lower a very small subset of Program(JSON v0)
|
||||
into MIR(JSON v0) strings without heavy parsing. Fail‑Fast with stable tags.
|
||||
- Use `builder_config_box.hako` (`hako.mir.builder.internal.builder_config`) to read all `HAKO_MIR_BUILDER_*` toggles.
|
||||
- Do not call `env.get` directly in lowers; prefer helper methods like:
|
||||
- `trace_enabled()`, `debug_enabled()`
|
||||
- `internal_on()`, `registry_on()`, `registry_only()`
|
||||
- `loop_jsonfrag_on()`, `jsonfrag_normalize_on()`, `skip_loops_on()`
|
||||
- `loop_adapter_return_mode()` → `string` (default) or `map`
|
||||
|
||||
Boxes
|
||||
- `prog_scan_box.hako` — tiny helpers for string scanning: find, skip spaces, read quoted/op/int values.
|
||||
- `lower_return_int_box.hako` — Return(Int N) → const(i64 N) + ret.
|
||||
- `lower_return_binop_box.hako` — Return(Binary(Int,Int) op {+,-,*,/}) → const, const, binop, ret.
|
||||
- `lower_if_compare_box.hako` — If(Compare(Int,Int) then Return(Int) else Return(Int)) → compare, branch, ret×2.
|
||||
- `lower_loop_simple_box.hako` — Loop(Compare i<limit) counting loop(i=0..limit)→ LoopFormBox.loop_count に委譲。
|
||||
- `lower_loop_sum_bc_box.hako` — Loop sum + break/continue 哲学(i==break → break / i==skip → continue)→ LoopFormBox.build("sum_bc", ...)。
|
||||
Notes
|
||||
- JsonFrag emission is kept default OFF and used for structural observation only. Semantics are prioritized by the normal path.
|
||||
|
||||
Policy
|
||||
- No execution or I/O; emit-only. Keep shapes minimal and obvious. For unsupported inputs, print
|
||||
`[mirbuilder/internal/unsupported] ...` and return null.
|
||||
|
||||
LoopForm param
|
||||
- LoopFormBox.build(mode, limit, skip, break)
|
||||
- mode: "count"(i を返す)/ "sum_bc"(sum の合流を Exit PHI で返す)
|
||||
- limit/skip/break は i64 として扱う。skip/break は null の場合、`skip=2` / `break=limit` を既定とする。
|
||||
|
||||
44
lang/src/mir/builder/internal/builder_config_box.hako
Normal file
44
lang/src/mir/builder/internal/builder_config_box.hako
Normal file
@ -0,0 +1,44 @@
|
||||
// builder_config_box.hako — Centralized env/toggles for MirBuilder
|
||||
// Purpose: avoid scattered env.get calls. All HAKO_MIR_BUILDER_* toggles are read here.
|
||||
|
||||
static box BuilderConfigBox {
|
||||
// Generic on/off reader for HAKO_MIR_BUILDER_* flags
|
||||
_is_on(key) {
|
||||
local v = env.get(key)
|
||||
if v == null { return 0 }
|
||||
local s = "" + v
|
||||
if s == "1" || s == "true" || s == "on" { return 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
// Trace controls
|
||||
trace_enabled() { return self._is_on("HAKO_MIR_BUILDER_TRACE") }
|
||||
debug_enabled() { return self._is_on("HAKO_MIR_BUILDER_DEBUG") || self._is_on("NYASH_CLI_VERBOSE") }
|
||||
|
||||
// Registry and internal lowers
|
||||
internal_on() {
|
||||
local v = env.get("HAKO_MIR_BUILDER_INTERNAL")
|
||||
// default ON
|
||||
return (v == null) || ("" + v == "1")
|
||||
}
|
||||
registry_on() {
|
||||
local v = env.get("HAKO_MIR_BUILDER_REGISTRY")
|
||||
// default ON
|
||||
return (v == null) || ("" + v == "1")
|
||||
}
|
||||
registry_only() { return env.get("HAKO_MIR_BUILDER_REGISTRY_ONLY") }
|
||||
|
||||
// Loop/JsonFrag related
|
||||
loop_jsonfrag_on() { return self._is_on("HAKO_MIR_BUILDER_LOOP_JSONFRAG") }
|
||||
jsonfrag_normalize_on() { return self._is_on("HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE") }
|
||||
skip_loops_on() { return self._is_on("HAKO_MIR_BUILDER_SKIP_LOOPS") }
|
||||
|
||||
// Return-mode for loop adapter: "string" (default) | "map"
|
||||
loop_adapter_return_mode() {
|
||||
local m = env.get("HAKO_MIR_BUILDER_LOOP_RETURN")
|
||||
if m == null { return "string" }
|
||||
local s = "" + m
|
||||
if s == "string" { return "string" }
|
||||
return "map"
|
||||
}
|
||||
}
|
||||
@ -39,6 +39,8 @@ static box JsonFragNormalizerBox {
|
||||
local const_list = new ArrayBox()
|
||||
local others_list = new ArrayBox()
|
||||
local seen = new MapBox() // signature -> 1
|
||||
// Dev-only: purify flag to drop builder-side allocations (e.g., newbox) from JSONFrag output
|
||||
local purify = 0; { local pv = env.get("HAKO_MIR_BUILDER_JSONFRAG_PURIFY"); if pv != null { local pvs = "" + pv; if pvs == "1" { purify = 1 } } }
|
||||
loop(i < n) {
|
||||
guard = guard + 1
|
||||
if guard > 4096 { break }
|
||||
@ -52,6 +54,9 @@ static box JsonFragNormalizerBox {
|
||||
i = ob_end + 1
|
||||
// classify by op
|
||||
local op = JsonFragBox.get_str(obj, "op")
|
||||
if purify == 1 {
|
||||
if op == "newbox" { continue }
|
||||
}
|
||||
if op == "phi" {
|
||||
phi_list.push(obj)
|
||||
continue
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
// Purpose: centralize MapBox creation/set so that we can later swap to JsonFrag-based
|
||||
// construction without touching all callers.
|
||||
|
||||
using "hako.mir.builder.internal.builder_config" as BuilderConfigBox
|
||||
|
||||
static box LoopOptsBox {
|
||||
new_map() {
|
||||
return new MapBox()
|
||||
@ -16,8 +18,7 @@ static box LoopOptsBox {
|
||||
using selfhost.shared.common.string_helpers as StringHelpers
|
||||
using "hako.mir.builder.internal.jsonfrag_normalizer" as JsonFragNormalizerBox
|
||||
// Opt-in: minimal MIR(JSON) construction for structure validation
|
||||
local jf = env.get("HAKO_MIR_BUILDER_LOOP_JSONFRAG")
|
||||
if jf != null && ("" + jf) == "1" {
|
||||
if BuilderConfigBox.loop_jsonfrag_on() == 1 {
|
||||
// Read limit if present, else default to 0 (safe)
|
||||
local limit = opts.get("limit"); if limit == null { limit = 0 }
|
||||
// Normalize to string
|
||||
@ -31,11 +32,15 @@ static box LoopOptsBox {
|
||||
"{\"op\":\"branch\",\"cond\":3,\"then\":1,\"else\":2}]}," +
|
||||
"{\"id\":1,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}," +
|
||||
"{\"id\":2,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}]}]}"
|
||||
print("[mirbuilder/internal/loop:jsonfrag]")
|
||||
if BuilderConfigBox.trace_enabled() == 1 { print("[mirbuilder/internal/loop:jsonfrag]") }
|
||||
// Optional: normalization (dev toggle)
|
||||
local norm = env.get("HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE")
|
||||
if norm != null && ("" + norm) == "1" {
|
||||
return JsonFragNormalizerBox.normalize_all(mir)
|
||||
if BuilderConfigBox.jsonfrag_normalize_on() == 1 { mir = JsonFragNormalizerBox.normalize_all(mir) }
|
||||
// Return mode: default string, optionally wrap into Map
|
||||
local mode = BuilderConfigBox.loop_adapter_return_mode()
|
||||
if mode == "map" {
|
||||
local m = self.new_map()
|
||||
m = self.put(m, "mir", mir)
|
||||
return m
|
||||
}
|
||||
return mir
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
using "hako.mir.builder.internal.loop_scan" as LoopScanBox
|
||||
using "hako.mir.builder.internal.loop_opts_adapter" as LoopOptsBox
|
||||
using "hako.mir.builder.internal.builder_config" as BuilderConfigBox
|
||||
|
||||
static box LowerLoopSimpleBox {
|
||||
try_lower(program_json) {
|
||||
@ -59,8 +60,7 @@ static box LowerLoopSimpleBox {
|
||||
|
||||
// JsonFrag 直組立(opt-in): HAKO_MIR_BUILDER_LOOP_JSONFRAG=1
|
||||
{
|
||||
local jf = env.get("HAKO_MIR_BUILDER_LOOP_JSONFRAG")
|
||||
if jf != null && ("" + jf) == "1" {
|
||||
if BuilderConfigBox.loop_jsonfrag_on() == 1 {
|
||||
// Minimal MIR(JSON) with compare + branch + ret(構造検証用)
|
||||
// Note: semanticsは簡略(canaryはトークン検出のみ)
|
||||
local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[" +
|
||||
@ -71,7 +71,7 @@ static box LowerLoopSimpleBox {
|
||||
"{\"op\":\"branch\",\"cond\":3,\"then\":1,\"else\":2}]}," +
|
||||
"{\"id\":1,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}," +
|
||||
"{\"id\":2,\"instructions\":[{\"op\":\"ret\",\"value\":1}]}]}]}"
|
||||
print("[mirbuilder/internal/loop:jsonfrag]")
|
||||
if BuilderConfigBox.trace_enabled() == 1 { print("[mirbuilder/internal/loop:jsonfrag]") }
|
||||
return mir
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user