CrownyJIT 3차 증분 — 다인자잎·비교확장·for·자족스텐실
개요
2026-07-05 3차 세션. 직전 세션(
2026-07-05-crownyjit-잔여3종-배선.md, FP지역·중첩·단일인자잎 완주)이
남긴 과제 4종을 배선. 전부
차등검증 게이트(채택 전 네이티브 vs 인터프리터 bit-identical, 불일치=영구 BAIL) 통과분만 채택.
공유
crownyc.c/
crownyc 무수정·무재빌드(20:01 타임스탬프 그대로). 산출물
crownyc-jit 별도.
4종 상태
| # | 목표 | 상태 | 요지 |
|---|
| 1 | 다인자 잎함수 인라인 | 완주 | 인자 2~4개 순수 잎함수. caller 소스순서 push↔프롤로그 역순 STORE 매핑(소비 k번째=소스 arity-1-k) |
| 2 | 비교 확장 | 완주 | LT(165)만→ EQ162·NEQ163·GT164·GTE173·LTE174 추가. guard·값 양쪽 |
| 3 | for(반복문) shape | 해당없음(확인 종결) | hanseonc_high 반복문 i 부터 A 까지 B는 동안(i<B)와 동일 캐노니컬 바이트코드(LT가드+JMPIFN+JMP백엣지) → 기존 shape로 이미 가속. 별도 배선 불요 |
| 4 | 자족(copy-and-patch) 1단계 | 완주(최소실증) | 캐노니컬 shape 1종을 cc 호출 0으로 스텐실 실행 실증 |
무엇을 배선했나
증분1 다인자 잎 인라인 (cj_transpile_leaf, cj_leaf_arity)
cj_leaf_arity(tgt): 표현식스택 깊이 시뮬로 프롤로그 파라미터 STORE 개수(arity, 최대4) 사전계산.
- 인자 매핑: caller가 arg0..arg_{n-1}을 소스순서로 push → LIFO라 프롤로그 STORE는 마지막 인자부터 소비.
소비 k번째 파라미터 = 소스 인덱스
arity-1-np. C함수 시그니처
cjfnK(long p0,..,long p_{arity-1}).
- caller(op247)는 스택의
es[esp-nargs..esp-1]을 소스순서 그대로 cjfnK(arg0,arg1,..)로 인라인.
- 실증: 2·3·4인자 잎(
(a*b+a)/7,(a*b+c)/7,(a*b+c-d)/7) 전부 byte-identical.
증분2 비교 확장 (cj_cmpop)
- opcode→C연산자 매핑 헬퍼. VM semantics
b=pop;a=pop;(a OP b)?T(1):A(-1) 정확 복제.
- loop·leaf 트랜스파일러 양쪽에 6종 비교 배선. guard(
동안(i>0) 등)·값(e=(i==5)) 양쪽 실증.
- 문자열핸들(≥20000) 비교는 VM=memcmp이나 JIT=정수비교 → 차등게이트가 MISMATCH로 BAIL(안전, 무오염).
증분3 for(반복문)
반복문 0..3000000 바이트코드 덤프 결과 = 동안(i<N) 캐노니컬 shape와 완전 동일
(header:
DATA Ai;LOAD;DATA N;LT;DATA exit;JMPIFN …
DATA header;JMP). 기존 지원으로 byte-identical 가속.
증분4 자족 스텐실 (copy-and-patch, cjstencil_canon/cj_stencil_try/cj_stencil_copy/cj_dispatch)
- 캐노니컬 shape 1종:
동안(i<N){ s=s+(i*i)/D; i=i+1 }(전역 정수, N·D 리터럴).
- 홀(hole) 바인딩: 런타임 피연산자(rd/wr 콜백·addr_s·addr_i·bound N·divisor D·maxiter·exited)를
cjhole_t struct로.
스텐실은 x0 포인터로만 접근 →
외부심볼·relocation 0 → 위치독립(copy-safe).
자족화 핵심 함정 해소:
signed char t[24] 스택배열 → 스택프로텍터(adrp 카나리 + bl __stack_chk_fail) 유발 → 복사 후 크래시.
해법: cjnorm 24트릿 균형절단을 모듈러 등가식으로 무배열 재작성(
r=v%3^24; r<0→+; r>LIM→-).
배열법과 6M+ 표본
0 diff 검증. → 스택배열 제거 → adrp/bl 소멸 → copy-safe.
rd/wr는 struct 포인터 통한 blr(register indirect)라 복사 후에도 정상.
실행: [cjstencil_canon, cjstencil_end_marker) span을 W^X 페이지(mmap RW→memcpy→mprotect RX→clear_cache)로.
cc 런타임 호출 0(setup 실측 ~4µs vs cc ~100ms+). cc 트랜스파일 경로는 폴백 유지.
- opt-in:
CROWNY_JIT_STENCIL=1일 때만 스텐실 우선 시도, 미매칭=cc 폴백. 차등게이트 동일 적용.
- 홀 일반화 실증: (N=3M,D=7)·(N=5M,D=13) 서로 다른 홀로 각각 채택, byte-identical.
신규 커널 벤치 (전부 인터프리터와 BYTE-IDENTICAL)
| 커널 | 인터프리터 | JIT | 배속 | 출력 | 경로 |
|---|
① 2인자 잎 (a*b+a)/7 1M | 1.55s | 1.04s | 1.5x | -33992113559 | cc+인라인 |
② GT guard i>0 3M | 3.54s | 0.97s | 3.6x | 96285415245 | cc |
③ for 반복문 0..3M | 3.59s | 1.02s | 3.5x | 101677582015 | cc(기존shape) |
④ 스텐실 i<3M /7 | 3.66s | 0.46s | 8.0x | 101677582015 | 스텐실(cc 0) |
④ 스텐실 i<5M /13 | 6.07s | 0.46s | 13.1x | -62224627314 | 스텐실(cc 0) |
- 3·4인자 잎, NE/LTE/GTE guard, EQ-as-value 전부 별도 byte-identical 확인(표 생략).
- 스텐실 경로가 cc 경로보다 빠름(canon /7: cc 1.02s vs 스텐실 0.46s) — cc 컴파일 대기(~0.2s+) 제거 효과.
- 스텐실 setup ~4µs(프로토타입 실측), cc 미기동 확인(temp파일 0).
회귀 (4종, 단일 write stdin — base==jitoff==jiton==jit+stencil 전부 IDENTICAL)
| 프로그램 | 입력 | 결과 |
|---|
| 크라우니코드뇌 | 0 1 1 0 0 | ✅ IDENTICAL |
| 래칫판정 | 0 55 60 5 | ✅ IDENTICAL |
| 작업구분 | 0+포트 상태 조회해줘 | ✅ IDENTICAL |
| 브레인결재 | 0 안건C 85 4 2 0 | ✅ IDENTICAL |
- JIT-off
crownyc-jit == 공유 crownyc(드리프트 0, 4종 재확인).
- finance 복리 재투자 시뮬(200k×60, FP지역 복리 + 다인자 잎
성장(잔액,3) 인라인):
인터프리터
17.63s → JIT 1.46s(~12x), byte-identical
200000, native_fires 199834.
관련 파일 (전부 /Users/ef/CrownyOS/crownyc/)
crownyc_jit_hot.c — ★트랜스파일러 본체. 3차 추가:
cj_leaf_arity(잎 arity 사전계산)·
cj_cmpop(비교 6종)·다인자 LPULL/시그니처/caller 인라인,
cjhole_t+
cjstencil_canon(자족 스텐실, 모듈러 cjnorm)·
cj_stencil_try(캐노니컬 매칭)·
cj_stencil_copy(W^X 복사)·
cj_dispatch(스텐실/cc 공통).
crownyc_jitmain.c — crownyc.c 복사본. 3차 무수정(배선은 전부 jit_hot.c 내부). 빌드:
cc -O2 -o crownyc-jit crownyc_jitmain.c -framework Security -framework CoreFoundation
crownyc-jit — 산출 바이너리(별도).
crownyc_jit_hot.한선 — 판정 로직 한선씨 동반본. 3차 추가: 다인자판정·비교연산자·for판정·스텐실판정(컴파일·실행 확인).
crownyc.c / crownyc — 공유, 무손상(20:01 타임스탬프 그대로).
남은 작업 (다음 세션 인수인계)
- 스텐실 shape 확대: 현재 캐노니컬 1종(
s+=(i*i)/D). 스텐실 스니펫 다종(누산변형·다변수·다연산)을
연결(concatenation)해 임의 정수루프를 조각 스텐실 조립으로 — 진짜 copy-and-patch 컴파일러.
- 스텐실 홀 = 코드 immediate 패치: 현재 홀=struct data. bound/divisor를 코드 immediate로 직접 패치(movz/movk 위치 스캔)하면 struct 로드 제거로 더 빠름.
- 비순수 잎·다탈출 가드·손익분기 게이팅(2차 인수인계 잔여 이월).
- 스텐실 W^X 엔타이틀먼트: 현재 plain mmap+mprotect(하드닝 미서명이라 동작). 배포 서명 시
com.apple.security.cs.allow-jit + MAP_JIT 필요.
안전수칙 준수
- 공유
crownyc.c/crownyc 무수정·무재빌드(20:01). 산출물 crownyc-jit 별도.
- 기본 오프(opt-in
CROWNY_JIT, 스텐실은 추가로 CROWNY_JIT_STENCIL). 부팅 self-test + 런타임 차등검증 게이트 이중 안전.
- 신규 영역(다인자·비교·스텐실) 전부 동일 게이트 통과분만 채택 — 트랜스파일/복사 버그는 출력 무오염(BAIL=인터프리터).
- 데몬·커밋·영속인프라 생성 없음.