An Incremental Approach to JIT Construction
JIT 컴파일러를 단계적으로 만들기
이 논문은 작은 Scheme 계열 언어를 확장하며 AOT 컴파일과 JIT 컴파일을 함께 구현하는 교육 과정을 제안합니다. Rust와 x86-64를 사용해 실행 메모리 버퍼, REPL의 지속 상태, 첫 호출 시점의 타입 특수화를 다루며 컴파일러 수업 두 차례에 적용했습니다.
- 주제
에디터 노트
교육용 JIT의 설득력은 기능 목록보다 단계마다 작동하는 구현을 제시하는 데 있습니다. 정수 하나를 반환하는 AOT 파이프라인과 같은 명령을 실행 버퍼에 넣는 JIT 경로를 나란히 보면 실행 메모리와 함수 포인터라는 차이를 구체적으로 배울 수 있습니다. 다만 제공된 설명에서 구체적인 구현은 정수 단계까지이며 REPL과 첫 호출 특수화는 초록에 요약된 수준입니다. 댓글도 접근하기 쉬운 설명이라는 인상을 전할 뿐 구현의 범위나 수업 효과를 검증하지는 않습니다. 따라서 이 자료는 JIT를 한 번에 완성하는 안내서보다 컴파일러 과제를 설계하는 교육 자료로 읽는 편이 정확합니다.
AI 요약
JIT 컴파일러의 실행 메모리 관리와 런타임 코드 생성은 AOT 컴파일 수업에서 다루기 어렵습니다. 저자들은 Ghuloum의 단계적 컴파일러 제작 방식을 확장해, 작은 S-expression 언어인 Snek에 기능을 하나씩 더하면서 매 단계 AOT 백엔드와 JIT 백엔드를 구현하는 교육 과정을 제시합니다. 구현 언어는 Rust이며, x86-64 기계어를 실행 가능한 버퍼에 생성하는 데 dynasm-rs를 사용합니다.
AOT와 JIT 구현
첫 단계의 언어는 64비트 정수 리터럴만 지원합니다. AOT 컴파일러는 어셈블리 파일을 만들고 nasm과 ar로 오브젝트 파일과 라이브러리를 만든 뒤 Rust 런타임에 연결합니다. 생성 코드는 결과를 rax에 놓고 반환합니다. JIT 모드에서는 dynasm으로 같은 기계어 명령을 실행 메모리에 직접 기록한 뒤 버퍼를 함수 포인터로 바꿔 같은 프로세스 안에서 호출합니다. 이 과정에는 Rust의 unsafe 블록이 필요합니다.
언어 확장과 교육 목표
논문 초록은 이후 변수와 REPL, 조건문, 변경 가능한 상태, 함수와 런타임 타입 최적화를 단계적으로 다룬다고 설명합니다. 완성 단계에서는 함수의 첫 호출에서 관찰한 인자 타입을 바탕으로 특수화된 함수 본문을 생성합니다. 저자들은 이 과정을 컴파일러 선택 과목에서 두 차례 가르쳤으며, 한 차례는 JIT 과제를 선택 사항으로 두고 다른 차례는 필수로 운영했습니다.
Lobsters 반응
- @BD103 — JIT 컴파일러는 늘 마법 같은 기술이라고 느꼈는데, 처음부터 만드는 과정을 이렇게 이해하기 쉽게 풀어낸 점이 정말 좋았습니다.
원문: ACM / 번역·요약: Trawling