← 목록
기타 2026-07-05 8KB 읽기 9분

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·값 양쪽
3for(반복문) 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;JMPIFNDATA 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 1M1.55s1.04s1.5x-33992113559cc+인라인
    ② GT guard i>0 3M3.54s0.97s3.6x96285415245cc
    ③ for 반복문 0..3M3.59s1.02s3.5x101677582015cc(기존shape)
    ④ 스텐실 i<3M /73.66s0.46s8.0x101677582015스텐실(cc 0)
    ④ 스텐실 i<5M /136.07s0.46s13.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 타임스탬프 그대로).

    남은 작업 (다음 세션 인수인계)

    1. 스텐실 shape 확대: 현재 캐노니컬 1종(s+=(i*i)/D). 스텐실 스니펫 다종(누산변형·다변수·다연산)을
    연결(concatenation)해 임의 정수루프를 조각 스텐실 조립으로 — 진짜 copy-and-patch 컴파일러.
    1. 스텐실 홀 = 코드 immediate 패치: 현재 홀=struct data. bound/divisor를 코드 immediate로 직접 패치(movz/movk 위치 스캔)하면 struct 로드 제거로 더 빠름.
    2. 비순수 잎·다탈출 가드·손익분기 게이팅(2차 인수인계 잔여 이월).
    3. 스텐실 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=인터프리터).
    • 데몬·커밋·영속인프라 생성 없음.