feat(phase21.5/22.1): MirBuilder JsonFrag refactor + FileBox ring-1 + registry tests

Phase 21.5 (AOT/LLVM Optimization Prep)
- FileBox ring-1 (core-ro) provider: priority=-100, always available, no panic path
  - src/runner/modes/common_util/provider_registry.rs: CoreRoFileProviderFactory
  - Auto-registers at startup, eliminates fallback panic structurally
- StringBox fast path prototypes (length/size optimization)
- Performance benchmarks (C/Python/Hako comparison baseline)

Phase 22.1 (JsonFrag Unification)
- JsonFrag.last_index_of_from() for backward search (VM fallback)
- Replace hand-written lastIndexOf in lower_loop_sum_bc_box.hako
- SentinelExtractorBox for Break/Continue pattern extraction

MirBuilder Refactor (Box → JsonFrag Migration)
- 20+ lower_*_box.hako: Box-heavy → JsonFrag text assembly
- MirBuilderMinBox: lightweight using set for dev env
- Registry-only fast path with [registry:*] tag observation
- pattern_util_box.hako: enhanced pattern matching

Dev Environment & Testing
- Dev toggles: SMOKES_DEV_PREINCLUDE=1 (point-enable), HAKO_MIR_BUILDER_SKIP_LOOPS=1
- phase2160: registry opt-in tests (array/map get/set/push/len) - content verification
- phase2034: rc-dependent → token grep (grep -F based validation)
- run_quick.sh: fast smoke testing harness
- ENV documentation: docs/ENV_VARS.md

Test Results
 quick phase2034: ALL GREEN (MirBuilder internal patterns)
 registry phase2160: ALL GREEN (array/map get/set/push/len)
 rc-dependent tests → content token verification complete
 PREINCLUDE policy: default OFF, point-enable only where needed

Technical Notes
- No INCLUDE by default (maintain minimalism)
- FAIL_FAST=0 in Bring-up contexts only (explicit dev toggles)
- Tag-based route observation ([mirbuilder/min:*], [registry:*])
- MIR structure validation (not just rc parity)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-10 19:42:42 +09:00
parent fc5706e3f2
commit 6055d53eff
135 changed files with 3983 additions and 1150 deletions

View File

@ -0,0 +1,12 @@
{
"bench": "box_create_destroy_small",
"ts": "2025-11-10T02:23:56+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 10,
"ny_vm_ms": 2116,
"ny_aot_ms": 0
}

View File

@ -0,0 +1,24 @@
{
"bench": "box_create_destroy_small",
"ts": "2025-11-10T02:12:21+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 9,
"ny_vm_ms": 2115,
"ny_aot_ms": 0
}
{
"bench": "box_create_destroy_small",
"ts": "2025-11-10T02:23:56+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 10,
"ny_vm_ms": 2116,
"ny_aot_ms": 0
}

View File

@ -0,0 +1,12 @@
{
"bench": "method_call_only_small",
"ts": "2025-11-10T02:24:06+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 9,
"ny_vm_ms": 2091,
"ny_aot_ms": 0
}

View File

@ -0,0 +1,24 @@
{
"bench": "method_call_only_small",
"ts": "2025-11-10T02:12:30+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 12,
"ny_vm_ms": 2104,
"ny_aot_ms": 0
}
{
"bench": "method_call_only_small",
"ts": "2025-11-10T02:24:06+09:00",
"host": "DESKTOP-K9SQDG2",
"unit": "ms",
"warmup": 1,
"repeat": 3,
"c_ms": 1,
"py_ms": 9,
"ny_vm_ms": 2091,
"ny_aot_ms": 0
}

View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Mirrors benchmarks/bench_box_create_destroy_small.hako
// Loop 1e4 times: create a tiny string, take length, accumulate, destroy.
int main(void) {
const int N = 10000; // 1e4 iterations
long long total = 0;
for (int i = 0; i < N; i++) {
char *tmp = (char*)malloc(2);
if (!tmp) return 2;
tmp[0] = 'x';
tmp[1] = '\0';
total += (long long)strlen(tmp);
free(tmp);
}
// Print total to avoid deadcode elimination; expected 10000
printf("%lld\n", total);
return 0;
}

View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <string.h>
// Mirrors benchmarks/bench_method_call_only_small.hako
// Loop 5e3 times: take length of preallocated string and accumulate.
int main(void) {
const int N = 5000; // 5e3 iterations
const char *s = "nyash";
long long total = 0;
for (int i = 0; i < N; i++) {
total += (long long)strlen(s);
}
// Print total to avoid deadcode elimination; expected 25000
printf("%lld\n", total);
return 0;
}

View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
# Mirrors benchmarks/bench_box_create_destroy_small.hako
# Loop 1e4 times: create a tiny string, take length, accumulate.
def main():
N = 10_000
total = 0
for _ in range(N):
# Force a fresh allocation; avoid literal interning
tmp = ''.join(['x'])
total += len(tmp)
# Print to avoid being optimized away
print(total)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python3
# Mirrors benchmarks/bench_method_call_only_small.hako
# Loop 5e3 times: take length of preallocated string and accumulate.
def main():
N = 5_000
s = "nyash"
total = 0
for _ in range(N):
total += len(s)
print(total)
if __name__ == "__main__":
main()