Skip to content

Complete iterative bytecode dispatch loop - #1

Draft
alexryndin wants to merge 1 commit into
masterfrom
complete-iterative-dispatch
Draft

alexryndin wants to merge 1 commit into
masterfrom
complete-iterative-dispatch

Conversation

@alexryndin

Copy link
Copy Markdown
Contributor

Work in progress based on TODO-1. This draft temporarily contains a source-export workflow so the branch can be built and tested locally; it will be removed before review.

alexryndin added a commit that referenced this pull request Jul 19, 2026
P15.34a — eliminate bcConstToValue re-interning (#1 perf hotspot, ~12.4%):
- Add resolveProtoConstants: at first Proto execution, replace compile-time
  *LuaString (hash seed 0) with VM-interned pointers (per-VM seed)
- bcConstToValue returns string constants directly — no re-hashing on every
  GETTABUP/GETFIELD/SETFIELD execution
- Called from pushBytecodeExecFrame AND TAILCALL frame-reuse path
- Ownership: after resolution, string constants owned by VM intern table,
  not by Proto (matching PUC's TString ownership model)
- Results: global_arith -54%, field_access -59%, metamethod_add -13%

P15.34b — PUC-faithful reader fixes (latent bug fixes):
- Nil-fill missing parameters in pushBytecodeExecFrame (PUC luaD_precall)
- Bound debug.getlocal/setlocal temp-scan by live_reg_top[pc] instead of
  scanning entire register window (fixes phantom temporaries from stale
  values)
- Fix parked-coroutine GC scan: walk per-frame live_reg_top[fr.pc] instead
  of flat bytecode_stack[0..parked_top] scan (fixes SIGSEGV on
  coroutine.lua/cstack.lua)
- cloneStrippedProto now copies live_reg_top
- @Memset(regs, .Nil) kept as safety net: live_reg_top is per-statement
  high-water mark, not per-instruction after-boundary like PUC's L->top.
  Removal is a P15.35 prerequisite.

Parity: 28/31 (no regressions), 44/44 smoke tests pass.
alexryndin added a commit that referenced this pull request Aug 5, 2026
- installSigintHandler/restoreSigintHandler: PUC docall (lua.c:161)
  installs SIGINT handler before runBytecode, restores SIG_DFL after.
- sigintHandler: PUC laction (lua.c:77-81) — sets global atomic flag
  and restores SIG_DFL so a second SIGINT terminates immediately.
- signal_int_pending checked in dispatch loop (every instruction) and
  in matchTokens (pattern matching hot path) — raises 'interrupted!'
  which pcall catches, matching PUC behavior.
- Pattern match budget: set to effectively unlimited (PUC has no step
  budget, only MAXCCALLS which our iterative matcher doesn't use).
  Fixes 'pattern too complex' for .*b on large strings.
- Result: SIGINT test #1 (pcall infinite loop) passes. Test #2 (long
  pattern search, n>=2) is a timing issue — PUC's debug-hook approach
  introduces natural delay; our direct flag check exits faster.
alexryndin added a commit that referenced this pull request Sep 11, 2026
…eSortLess rewritten (ccallEnter(.nonyieldable) BEFORE resolveCallable so __call resolution + child CALL hook fire inside the window, PUC ldo.c:652; all 6 coroutine_yield special cases + 'invalid order function' error-wrapping DELETED — comparator errors propagate unwrapped, PUC sort_comp lua_call), bare-message mechanism = callBuiltin always pushes builtin C-frame first so builtinCoroutineYield failRunerror sees C-frame on top (no position prefix, PUC luaB_yield); builtinTableSort comparator checktype (raw tag, no __call resolution, ltablib.c:399) 'bad argument #2 to sort (function expected, got X)'; 'invalid order function' sites fail→failArgerror (luaL_where(1): position from Lua, absent when caller is C); follow-on arg-error naming parity (errors.lua:381 regression exposed accidental pass via wrapping message): _G in _LOADED (luaopen_base), pushGlobalFuncName (loaded-search, findfield L2, strip _G., tag-guarded Value compare), failTabArgerror, checkTabArg arg_no (fixes pre-existing hardcoded #1 for table.move arg-4), 7 call sites — table.sort messages byte-match PUC (qualified name C-context, call-site name from-Lua, no-pos via pcall); side-fix undump fixed-borrow alignment (latent UB exposed by arena offset shift from _G registration, unit Task 7.3 crash): fixed_borrow = base % 4 check with copy fallback (PUC plain-casts = UB on misaligned base; both code/lineinfo blocks 4-aligned relative to same base = all-or-nothing), flags.fixed_arrays = fixed_borrow keeps destroyProtoTree/footprint exact; smoke 78_table_sort_yieldability.lua T0-T10 byte-identical (T12 dropped: pre-existing trampoline lost-continuation crash — coroutine → comparator → resume other → crash, reproduces on pre-P16.37 binary, backlog with reproducers); negative validation: neutralized nny-enter → P1 suspends (old divergence reproduced), restored → byte-identical; backlog documented: trampoline crash, coroutine.close/setmetatable arg messages, comparator call counts (algorithmic); gates: fmt, unit D+RF 217/217, smoke 77/77, matrix --testc zig_fail=0 (errors.lua pass, big.lua both_fail pre-existing), c_api test + test-diff PASS (TBC 22+23), api580 GREEN
alexryndin added a commit that referenced this pull request Sep 18, 2026
…→ C2=200cae7, RF binary 97ee5179e631110e…): единый current-* provenance на 200cae7/97ee5179 — snapshot (geomean 1.41x), dispatch-floor, differential-profile (10 workloads), codesize (.text 2600441, runBytecodeDispatch 71241), callframe-layout свежими пробами p50r2 (CallFrame 88/u@32 оба режима), matrix (31/32 zig_fail=0) + smoke 84/84 через status_snapshot + сгенерированные блоки README/STATUS; current-gate/manifest = объявленная сессия #2 на C2-binary (RESULT OK; manifest artifact sha 441c4851 == gate file); сессия #1 (92d115c3, binary после C) тоже RESULT OK — обе recorded, история append-only; STATUS: P16.50-review checkbox закрыт (open-count 22→21), фазовая запись: три blocker'а + error propagation + HIGH + finding 4 + cleanup + negative-валидации + C2-фикс (fixed-size worklist OOB на >16 upvalues — calls.lua SIGSEGV, найден финальной батареей) + честные residuals (cell.set при post-commit barrier-провале недостижим через реальный dispatch; c_panicf не вводён; частичный gray-при провале old1-append); батарея 13/13 + crash-loop 20/20. Wrapper-scope: git diff C2..D по src/build.zig/tests/tools-*.py пуст
alexryndin added a commit that referenced this pull request Sep 25, 2026
P15.34a — eliminate bcConstToValue re-interning (#1 perf hotspot, ~12.4%):
- Add resolveProtoConstants: at first Proto execution, replace compile-time
  *LuaString (hash seed 0) with VM-interned pointers (per-VM seed)
- bcConstToValue returns string constants directly — no re-hashing on every
  GETTABUP/GETFIELD/SETFIELD execution
- Called from pushBytecodeExecFrame AND TAILCALL frame-reuse path
- Ownership: after resolution, string constants owned by VM intern table,
  not by Proto (matching PUC's TString ownership model)
- Results: global_arith -54%, field_access -59%, metamethod_add -13%

P15.34b — PUC-faithful reader fixes (latent bug fixes):
- Nil-fill missing parameters in pushBytecodeExecFrame (PUC luaD_precall)
- Bound debug.getlocal/setlocal temp-scan by live_reg_top[pc] instead of
  scanning entire register window (fixes phantom temporaries from stale
  values)
- Fix parked-coroutine GC scan: walk per-frame live_reg_top[fr.pc] instead
  of flat bytecode_stack[0..parked_top] scan (fixes SIGSEGV on
  coroutine.lua/cstack.lua)
- cloneStrippedProto now copies live_reg_top
- @Memset(regs, .Nil) kept as safety net: live_reg_top is per-statement
  high-water mark, not per-instruction after-boundary like PUC's L->top.
  Removal is a P15.35 prerequisite.

Parity: 28/31 (no regressions), 44/44 smoke tests pass.
alexryndin added a commit that referenced this pull request Sep 25, 2026
- installSigintHandler/restoreSigintHandler: PUC docall (lua.c:161)
  installs SIGINT handler before runBytecode, restores SIG_DFL after.
- sigintHandler: PUC laction (lua.c:77-81) — sets global atomic flag
  and restores SIG_DFL so a second SIGINT terminates immediately.
- signal_int_pending checked in dispatch loop (every instruction) and
  in matchTokens (pattern matching hot path) — raises 'interrupted!'
  which pcall catches, matching PUC behavior.
- Pattern match budget: set to effectively unlimited (PUC has no step
  budget, only MAXCCALLS which our iterative matcher doesn't use).
  Fixes 'pattern too complex' for .*b on large strings.
- Result: SIGINT test #1 (pcall infinite loop) passes. Test #2 (long
  pattern search, n>=2) is a timing issue — PUC's debug-hook approach
  introduces natural delay; our direct flag check exits faster.
alexryndin added a commit that referenced this pull request Sep 25, 2026
…eSortLess rewritten (ccallEnter(.nonyieldable) BEFORE resolveCallable so __call resolution + child CALL hook fire inside the window, PUC ldo.c:652; all 6 coroutine_yield special cases + 'invalid order function' error-wrapping DELETED — comparator errors propagate unwrapped, PUC sort_comp lua_call), bare-message mechanism = callBuiltin always pushes builtin C-frame first so builtinCoroutineYield failRunerror sees C-frame on top (no position prefix, PUC luaB_yield); builtinTableSort comparator checktype (raw tag, no __call resolution, ltablib.c:399) 'bad argument #2 to sort (function expected, got X)'; 'invalid order function' sites fail→failArgerror (luaL_where(1): position from Lua, absent when caller is C); follow-on arg-error naming parity (errors.lua:381 regression exposed accidental pass via wrapping message): _G in _LOADED (luaopen_base), pushGlobalFuncName (loaded-search, findfield L2, strip _G., tag-guarded Value compare), failTabArgerror, checkTabArg arg_no (fixes pre-existing hardcoded #1 for table.move arg-4), 7 call sites — table.sort messages byte-match PUC (qualified name C-context, call-site name from-Lua, no-pos via pcall); side-fix undump fixed-borrow alignment (latent UB exposed by arena offset shift from _G registration, unit Task 7.3 crash): fixed_borrow = base % 4 check with copy fallback (PUC plain-casts = UB on misaligned base; both code/lineinfo blocks 4-aligned relative to same base = all-or-nothing), flags.fixed_arrays = fixed_borrow keeps destroyProtoTree/footprint exact; smoke 78_table_sort_yieldability.lua T0-T10 byte-identical (T12 dropped: pre-existing trampoline lost-continuation crash — coroutine → comparator → resume other → crash, reproduces on pre-P16.37 binary, backlog with reproducers); negative validation: neutralized nny-enter → P1 suspends (old divergence reproduced), restored → byte-identical; backlog documented: trampoline crash, coroutine.close/setmetatable arg messages, comparator call counts (algorithmic); gates: fmt, unit D+RF 217/217, smoke 77/77, matrix --testc zig_fail=0 (errors.lua pass, big.lua both_fail pre-existing), c_api test + test-diff PASS (TBC 22+23), api580 GREEN
alexryndin added a commit that referenced this pull request Sep 25, 2026
…→ C2=2759e25, RF binary 97ee5179e631110e…): единый current-* provenance на 2759e25/97ee5179 — snapshot (geomean 1.41x), dispatch-floor, differential-profile (10 workloads), codesize (.text 2600441, runBytecodeDispatch 71241), callframe-layout свежими пробами p50r2 (CallFrame 88/u@32 оба режима), matrix (31/32 zig_fail=0) + smoke 84/84 через status_snapshot + сгенерированные блоки README/STATUS; current-gate/manifest = объявленная сессия #2 на C2-binary (RESULT OK; manifest artifact sha 441c4851 == gate file); сессия #1 (92d115c3, binary после C) тоже RESULT OK — обе recorded, история append-only; STATUS: P16.50-review checkbox закрыт (open-count 22→21), фазовая запись: три blocker'а + error propagation + HIGH + finding 4 + cleanup + negative-валидации + C2-фикс (fixed-size worklist OOB на >16 upvalues — calls.lua SIGSEGV, найден финальной батареей) + честные residuals (cell.set при post-commit barrier-провале недостижим через реальный dispatch; c_panicf не вводён; частичный gray-при провале old1-append); батарея 13/13 + crash-loop 20/20. Wrapper-scope: git diff C2..D по src/build.zig/tests/tools-*.py пуст
alexryndin added a commit that referenced this pull request Sep 30, 2026
…й luaL_typeerror→luaL_argerror путь (закрывает lauxlib argument-error BLOCKER; open-count 26→25)

Дефект (reviewer-oracle на 00a5ea0): PUC «bad argument #1 to '?'
(string expected, got boolean)», luazig — без «to '?'»: ручной
lua_pushfstring в luaL_checklstring/optlstring/checkoption и
существующий luaL_typeerror обошли общий аргументный механизм.

Fix — ОДИН общий PUC 5.5 путь (lauxlib.c:171-208):
- luaL_typeerror: msg = «%s expected, got %s» → luaL_argerror.
- luaL_argerror: getstack(L,0) fail → luaL_error «bad argument #N (%s)»;
  getinfo "n"; namewhat=="method" → arg-- и arg==0 → «calling '%s' on
  bad self (%s)»; ar.name==NULL → pushglobalfuncname (pushGlobalFuncName
  через registry._LOADED — cidx cut-1 owner; cFuncEqual для PUC VLCF
  rawequal-семантики сравнения) или '?'; → luaL_error «bad argument #N
  to 'NAME' (EXTRA)».
- luaL_error: where(L,1)-prefix + vfstring + concat + lua_error.
- luaL_checklstring/optlstring non-string → luaL_typeerror;
  luaL_checkoption invalid → luaL_argerror(«invalid option '%s'»).
Никаких format-by-name special cases; RuntimeError ≠ OOM (error-path
push'и через cThrowOn).

Canonical 35_lauxlib_argerror (+PUC-ref, Makefile): 28 контекстов
(host-pcall + Lua call-sites) — host-C '?'-форма (= reviewer-оракул
byte-exact), missing argument («no value»), lightuserdata,
__name-metatable typearg, Buffer-typearg, method/self, named-function.
Byte-exact PUC 5.5 Debug и RF. Negative-before pristine 6bfacc2
дословно (без to '?'); mutation короткого шаблона → RED → revert.
Прежние 30-34 не регрессировали (33_getset «attempt to index...» —
другой error-класс).

Гейты: battery 358/358 Debug+RF 0 leaks; matrix --testc (свежий RF)
zig_fail=0 (big.lua both_fail pre-existing); smoke PASS; c_api 24-35
DIFF PASS оба режима; api580 GREEN; fmt/diff-check clean. Perf: меняется
только cold error path — native A/B неприменим (аргументировано).

Findings: документированная граница — PUC 5.5 ar.extraargs
(CIST_CCMT __call-chain count) не персистится per-frame (документировано
в коде + probe; смежно debug.getinfo("t").extraargs vararg-count zig 3
vs PUC 0 — тот же корень) — ARCHITECTURAL-BACKLOG; ORDINARY-BACKLOG:
остальные ручные шаблоны (checkudata/checkinteger/checktype/checkany/
checknumber); LOW: debugFindGlobalFuncName pointer-only compare.
STATUS: lauxlib-BLOCKER закрыт; open-count 26→25.
alexryndin added a commit that referenced this pull request Sep 30, 2026
…ame owner дизайн + 2-cut план (research; product не менялся; CCMT-BLOCKER дополнен evidence; open-count без изменений)

Bounded research (промпт-условие lauxlib-коррекции выполнено: контракт
отсутствует — задокументирован вместо молчаливого закрытия). Сабагент по
брифу; отчёт /tmp/opencode/ccmt_report.md (452 строки) + оракулы
/tmp/opencode/ccmt/ (23 формы, raw, статическая линковка, source/binary
identity pristine 8ac6808).

(1) PUC-контракт полностью (ldo.c:523-536 tryfuncTM → prepCallInfo
628-636; ldebug.c:356-364; lauxlib.c:171-194; lstate.h:226-227):
счётчик — биты 8-11 callstatus кадра вызываемого, коммит при
активации. Открытая PUC-квирка подтверждена оракулом:
luaD_pretailcall Lua-ветка выбрасывает новый счётчик (stale-биты
кадра: F7a 2 / F7b F5c 0), C-ветка коммитит в свежий C-кадр (F7c).

(2) Negative-before 23 формы / 17 расходятся: решающий расхват
(PUC «bad extra argument #1 to 't'» vs zig «bad argument #1»);
off-by-one предел (PUC 15 звеньев, zig 16 — оба пути); чужой
overflow-текст на resolveCallable-пути; vararg-count под именем
extraargs (F6a: 3 vs 0); потеря счётчика на C-кадрах (F6d/e); после
yieldk (F9); stale-preserve (F7a).

(3) Дизайн: владелец — уже объявленные мёртвые биты 8-11 callstatus
(0 новых байт; CallFrame 88 ≤ 104); писатели — 3 choke-точки активации
(stageFixedCall 17723 / pushStagedBytecodeExecFrame 17942 /
initBuiltinCFrame 9307); tailcall-reuse — не писать (PUC-parity);
grep-полный inventory: 2 резолюции-хелпера, 15 resolveCallable
call-сайтов, 3 bytecode-цикла.

(4) Cut-план: Cut 1 frame-контракт + Lua-уровневый getinfo 't' +
предел/overflow-текст (гейт: Lua-формы оракула byte-exact); Cut 2
lua_Debug.extraargs ABI (sizeof 136→144, extraargs@63 — измерено;
header НЕ менялся) + luaL_argerror renumbering («extra argument»
ветка) + пересборка tracked ELF. Альтернатива B (коммит после push)
описана. Perf-план: +2 ALU-опа на активацию (без branch, PUC-идент);
обязательное измерение lua_calls + perf_compare paired seeds.

Findings: MEDIUM where-attribution runtime-ошибок при текущем C-кадре
(PUC без prefix, zig с — F4n17/F8n17; переживает CCMT-фикс,
ORDINARY-BACKLOG); UNCONFIRMED re-push C-кадра при suspend (решающий
эксперимент = F9-гейт Cut 1). STATUS: CCMT-BLOCKER дополнен; открыт до
implementation (после ревью дизайна и решения владельца — меняется
общий call-frame контракт); open-count без изменений. Product/perf не
тронуты.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant