목표 및 아키텍처 개요¶
상위 목표¶
전통적으로, 언어 인터프리터는 C/Posix, Java, C# 같은 대상 플랫폼 언어로 작성됩니다. 각 구현은 애플리케이션 소스 코드와 대상 환경 사이의 근본적인 매핑을 제공합니다. 언어 구현자가 언어 구현을 작성하는 것을 지원하기 위해 표준화되고 더 높은 수준의 기능을 제공하는 것은, .NET 프레임워크와 어느 정도는 Java 가상 머신 같은 “모든 것을 아우르는” 환경의 목표 중 하나입니다.
PyPy는 더 야심찬 접근 방식을 실험하고 있습니다. 우리는 고수준 언어 Python의 부분 집합인 RPython 언어을 사용하는데, 이를 통해 저수준 세부 사항에 대한 참조와 의존성이 거의 없는 단순한 인터프리터 형태로 언어를 작성합니다. RPython 툴체인은 적절한 저수준 요소를 삽입하여 우리가 선택한 플랫폼에 맞는 구체적인 가상 머신을 생성합니다. 그 결과물은 다른 기능 및 플랫폼 구성을 선택하여 사용자 정의할 수 있습니다.
저희의 목표는 언어 구현자들이 겪는 문제, 즉 o 개의 중요한 설계 결정을 가진 l 개의 동적 언어와 p 개의 플랫폼을 위해 l * o * p 개의 인터프리터를 작성해야 하는 문제에 대한 가능한 해결책을 제공하는 것입니다. PyPy는 이러한 변수들을 각각 독립적으로 변경할 수 있도록 하는 것을 목표로 합니다:
l: 분석 대상인 언어를 발전시키거나 완전히 교체할 수 있습니다.o: 번역(translation) 과정을 조정하고 최적화하여 다양한 모델과 트레이드오프에 기반한 플랫폼별 코드를 생성할 수 있습니다;p: 우리는 다양한 물리적·가상 플랫폼을 대상으로 하는 새로운 번역기(translator) 백엔드를 작성할 수 있습니다.
반면, .NET과 같은 표준화된 대상 환경은 그 영역 안에서는 p=1을 강제합니다. 이는 더 높은 수준의 기반을 제공하여 o를 좀 더 작게 만드는 데 도움이 됩니다. 그럼에도 우리는 하나의 공통 환경 사용을 강제하는 것이 필요하지 않다고 믿습니다. PyPy의 목표는 - 적어도 언어 구현에 관한 한 - 표준화에 의존하지 않는 l * o * p 문제에 대한 접근법을 보여줌으로써 이 주장에 힘을 싣는 것입니다.
이 목표에서 가장 야심 찬 부분은 소스 인터프리터를 대상 플랫폼용 인터프리터로 번역(translation)하는 데 그치지 않고, 언어에 독립적인 방식으로 Just-In-Time 컴파일러를 생성하는 것입니다. 이는 관련된 복잡성으로 인해 언어 구현에서 일반적으로 매우 어렵다고 여겨지는 영역입니다.
아키텍처¶
RPython 툴체인의 역할은 RPython 언어 프로그램을 다양한 대상 플랫폼 중 하나를 위한 해당 프로그램의 효율적인 버전으로 번역(translation)하는 것이며, 그 대상은 일반적으로 Python보다 상당히 저수준입니다.
저희가 취한 접근법은 소스 RPython 프로그램의 추상화 수준을, 높은 수준에서부터 목표 플랫폼이 무엇이든 그 수준에 이르기까지, 여러 단계에 걸쳐 낮추는 것입니다. 현재 저희는 두 가지 큰 부류의 목표 플랫폼을 지원합니다: 구조체와 포인터를 갖춘 C와 유사한 메모리 모델을 가정하는 것과, 클래스, 인스턴스, 메서드를 갖춘 객체 지향 모델을 가정하는 것(예를 들어 Java와 .NET 가상 머신이 그러하듯이)입니다.
RPython 툴체인은 RPython 소스 코드나 구문 트리를 전혀 보지 않으며, 오히려 입력으로 주어진 함수 객체의 동작을 정의하는 코드 객체에서 시작합니다. 이는 미리 임포트된 RPython 프로그램을 대상 플랫폼에 적합한 실행 가능한 형태로 “동결”하는 것으로 볼 수 있습니다.
번역(translation) 과정의 단계는 다음과 같이 요약할 수 있습니다:
- 각 소스 함수의 코드 객체는 흐름 그래프 빌더에 의해 제어 흐름 그래프로 변환됩니다.
- 제어 흐름 그래프는 Annotator에 의해 처리되며, 이는 전체 프로그램에 대한 타입 추론을 수행하여 제어 흐름 그래프의 각 변수에 실행 시점에 가질 수 있는 타입을 주석으로 답니다.
- 애노테이터가 제공한 정보는 RTyper가 제어 흐름 그래프의 고수준 연산을 대상 플랫폼의 추상화 수준에 더 가까운 연산으로 변환하는 데 사용됩니다.
- 선택적으로, 그런 다음 다양한 변환 <optional-transformations>을 적용할 수 있으며, 이는 예를 들어 인라이닝과 같은 최적화를 수행하거나, 스택리스 방식의 동시성과 같은 기능을 추가하거나, 가비지 컬렉터를 위한 코드를 삽입합니다.
- 그런 다음, 그래프는 대상 플랫폼용 소스 코드로 변환되고 실행 파일로 컴파일됩니다.
이 과정은 RPython 툴체인에 관한 문서와 논문 Compiling dynamic language implementations에 훨씬 더 자세히 설명되어 있습니다.
더 읽을거리¶
- RPython 시작하기: PyPy 소스 코드 참여를 위한 실전 가이드입니다.
- PyPy’s approach to virtual machine construction: OOPSLA 2006에 부속된 Dynamic Languages Symposium에서 발표된 논문입니다.
- 번역(translation) 문서: 저희 번역(translation) 프로세스에 대한 상세한 설명입니다.
- JIT Generation in PyPy는 인터프리터로부터 Just-in-time 컴파일러를 만들어내는 방법을 설명합니다.
- 이 자습서는 implement your own interpreter하기 위해 RPython 툴체인을 사용하는 방법을 다룹니다.