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

CrownyJIT 5차 — 배열 원소()/설정() 네이티브 지원 (실서비스 관문 돌파)

개요

3차/4차가 남긴 "실서비스 후보 3종 전부 가속 0배" 관문의 원인은 루프 내 배열 접근 (원소()/설정())이 트랜스파일러 화이트리스트 밖 → 전량 BAIL이었다. 5차는 그 관문을 뚫었다. 배열 읽기/쓰기 opcode를 cc-경로 트랜스파일러(잎 인라인 포함)에 추가하고, 쓰기 루프의 동적 배열힙 주소를 차등게이트가 안전 검증하도록 확장했다. 공유 crownyc.c/crownyc 무접촉(20:01), 산출물 crownyc-jit 별도. 모든 채택은 런타임 차등검증(byte-identical) 통과분만.

배열 표현 요약 (crownyc.c 정독 결과, 3줄)

  • 배열 = 전역 큐브아레나 memory[]base주소(int ≥10000). 레이아웃 [base+0..4095]=원소,
[base+4096]=길이. 스택에 올라가는 "핸들"=base 정수. (ARRAY_BLOCK=4097, CAP=4095)
  • 원소/꺼내(INDEX 407)=경계검사 읽기 memory[base+i]; 설정(ARRAY_SET 415)=제자리 쓰기
후 base 반환(길이 슬롯 자동확장); 추가(APPEND 408)=제자리.
  • 배열은 bump 할당(mem_count += 4097)이라 GC 이동/재배치 없음base+i 절대주소가
안정적 → rd/wr(base+i) 콜백이 메모리안전(콜백 안전경로 채택, 인라인 주소계산 불요).

지원 상태 (crownyc_jit_hot.c)

opcode한선씨cc-루프잎(leaf)안전장치
407 INDEX원소/꺼내(arr,i)rd(base+i)읽기전용=정적스냅샷 충분
406 LEN길이(arr)rd(base+4096)문자열핸들=게이트 MISMATCH→BAIL
415 ARRAY_SET설정(arr,i,v)wr(base+i,v)+base반환배열힙 영역스냅샷으로 차등검증
- 잎 인라인: 잎 함수 시그니처에 rd/wr 콜백을 선두인자로 전달 → 행렬원소(m,r,c)=원소(m,r*4+c) 같은 잎이 인라인됨. arity 사전계수(cj_leaf_arity)에도 407/406/415 반영(누락 시 잎판정 전 BAIL — 실측 중 발견·수정).
  • 쓰기 차등게이트: 정적 taddr(변수슬롯<10000)만으론 부족 → 쓰기루프는 배열힙 [10000..mem_count)
전 영역을 스냅샷/복원해 native·인터프리터 양쪽 배열변경을 정확 비교. 영역>2M 큐브면 BAIL(폴백). mem_count도 게이트 전후 저장/복원(프로브 힙증가 누수 차단).
  • asm 스니펫 경로는 배열 미지원(순수 스칼라 전용) → 배열루프는 자동 cc-경로.

실서비스 재실측 (best-of-3, 캐시 워밍, 단일 wall-clock)

워크로드base(no-JIT)jit-offjit-on배속identical4차(전)
배열합(순수 원소/INDEX 읽기)4.68s4.77s0.56s8.4×— (신규 미분류 클래스)
배열쓰기(설정/ARRAY_SET)5.17s5.24s0.81s6.4×
3D렌더러(행렬곱, 행렬원소 잎인라인)3.88s3.92s2.45s1.58×0× (JIT 켜면 오히려 느림)
유체시뮬(16×16×150)0.19s0.20s0.20s1.0×
ARIMA(n=200,p=8)0.35s0.35s0.35s1.0×
  • 관문 돌파: 배열접근 루프가 이전엔 100% BAIL(compiled=0) → 이제 컴파일·가속.
배열 읽기 클래스 8.4×, 쓰기 클래스 6.4×(둘 다 byte-identical). 3D렌더러(실서비스)는 compiled=1, leaves_inlined=2, native_fires=1895010×→1.58× (전엔 JIT가 느리게 만들던 것).
  • 3D가 >2× 못 넘은 이유: 컴파일된 핫루프가 4x4 행렬의 내부 k-루프(4반복)뿐 —
루프진입당 인터프리터 1반복+디스패치 고정비가 4반복을 희석. 외곽 r/c-루프는 중첩(내부 백엣지 포함) +행렬생성 할당루프라 단일-shape 위반으로 BAIL. (배열합/배열쓰기 마이크로벤치는 4000반복이라 관문 돌파 효과가 온전히 드러남.)
  • 유체/ARIMA가 여전히 0×인 이유: 핫루프 관용구 숫자변환(문자열변환(배열[i])) = TOSTR(488)/
TOINT(486) 문자열핸들 opcode — 문자열풀 할당(480k 캡 원인)이라 JIT 화이트리스트에서 의도적 제외. 라이브러리를 직접 인덱싱으로 바꾸면 배열합처럼 가속 가능(라이브러리 수정 금지 지시로 미착수).

자기검사 캐시 (부팅 cc-spawn 고정비 절감)

  • 부팅 self-test의 cc스폰(실측 ~0.39s)이 JIT-on 상시 고정비. cc툴체인 결정론적이라 최초 PASS 후
마커파일(/tmp/.crownyjit_selftest_ok)로 cc검증 생략. 무효화=/usr/bin/cc mtime>마커(툴체인갱신), CROWNY_JIT_NOCACHE=1 강제재검증. 안전: 런타임 게이트가 모든 실루프를 재검증하므로 캐시오류=성능만.
  • 실측: trivial 프로그램 콜드 0.90s → 캐시 0.56s(-0.34s).

회귀 (base==jitoff==jiton IDENTICAL, md5)

  • 11/11 PASS: canon3M·arb2M·finance복리3M(스칼라 무영향), 배열합·배열쓰기·3D·유체·ARIMA,
crownyc_jit_hot.한선, 작업구분·브레인결재(기능 프로그램, stdin). 4모드(base/off/on/asm) 일치.
  • 공유 crownyc.c(20:01:25)·crownyc(20:01:53) mtime 무손상. JIT-off crownyc-jit==공유 crownyc(드리프트0).
  • 주의(실측 함정): env CROWNY_JIT=(빈 문자열)은 getenv non-NULL → JIT 켜짐. 진짜 off는
env -u CROWNY_JIT. (초기 측정에서 "jitoff"가 실은 on이라 배속이 과소평가됐던 것을 교정.)

관련 파일 (전부 /Users/ef/CrownyOS/crownyc/)

  • crownyc_jit_hot.c — ★본체. 5차 추가: cc-루프/잎 트랜스파일러 407/406/415 케이스, 잎 rd/wr
선두인자 전달, cj_leaf_arity 407/406/415 반영, 차등게이트 배열힙 영역스냅샷(cj_has_write· CJ_WRITE_SNAP_CAP)·mem_count 저장복원, self-test 마커캐시(cj_selftest_cache_*).
  • crownyc_jit_hot.한선 — 판정 로직 한선씨 동반본. 5차 증분H~K(배열접근·쓰기게이트·잎배열·캐시 판정).
  • crownyc_jitmain.c/crownyc_jit_snippets.s — 5차 무수정. 빌드:
cc -O2 -o crownyc-jit crownyc_jitmain.c crownyc_jit_snippets.s -framework Security -framework CoreFoundation
  • crownyc.c/crownyc — 공유, 무접촉(20:01).
  • 벤치/회귀 드라이버: /tmp/JIT실적용/{배열합,배열쓰기,canon,arb,finance,3D렌더러,유체시뮬,ARIMA}.한선.

env 플래그 (5차 추가)

  • CROWNY_JIT_NOCACHE=1 — self-test 마커캐시 무시(항상 cc재검증).
  • 기존: CROWNY_JIT=1(켬), CROWNY_JIT_HOT=N, CROWNY_JIT_ASM/STENCIL/GATE/DUMP/TIME.

잔여 이슈 (다음 세션 인수인계)

  1. 3D렌더러 >2× 미달: 내부 k-루프(4반복)만 컴파일. 외곽 중첩루프 JIT(내부 백엣지 허용)·
또는 4x4 언롤 잎을 인라인하면 진입당 고정비 희석 해소 여지.
  1. 유체/ARIMA 0× 잔존: 핫루프의 숫자변환(문자열변환(배열[i])) 문자열핸들 관용구가 원인.
라이브러리를 직접 인덱싱(원소() 직접 정수)으로 바꾸면 배열합급 가속(라이브러리 수정 금지로 보류).
  1. 쓰기루프 성능: 원소/설정이 매회 rd/wr 콜백(blr) — 접촉 배열base를 callee-saved 레지스터에
호이스팅하면 추가 가속(4차 남은과제 1과 동일 축). 현재도 6.4×라 우선순위 낮음.
  1. 배열힙 영역스냅샷은 O(mem_count) — 큰 힙 프로그램의 쓰기루프는 상한(2M)에서 BAIL. 접촉주소
write-log 방식으로 정밀화하면 큰 힙에서도 쓰기가속 가능(단 인터프리터 쓰기 포착 필요).