64비트 PyPy와 Windows¶
PyPy가 64비트 Windows에서 동작하게 해 달라는 요청은 오래전부터 있었으며, 다른 면에서는 저주받은 해였던 2020년에 마침내 해결되었습니다. 문제는 RPython의 정수 타입(rffi.SIGNED)이 정수로 캐스팅된 포인터 값을 (때때로) 담을 수 있을 만큼 충분히 크다고 가정한다는 점입니다. 대부분의 플랫폼에서는 이에 대응하는 C 타입인 long이 이 조건을 만족합니다. 하지만 64비트 Windows에서는 long이 32비트인 반면, sizeof(void*)는 64비트입니다. 가장 간단한 해결책은 rffi.SIGNED가 64비트 정수를 담을 수 있도록 보장하는 것이며, 그 결과 Win64에서 CPython과 PyPy 사이에 다음과 같은 비호환성이 있는 python2가 만들어집니다:
CPython: sys.maxint == 2**31-1, sys.maxsize == 2**63-1
PyPy: sys.maxint == sys.maxsize == 2**63-1
…그리고 이에 따라 PyPy2는 int가 long으로 변환되기 전까지 더 큰 값인 sys.maxint까지의 int를 지원합니다.
수행한 작업¶
가장 먼저 한 일은 이 모델에 맞을 때까지 CPython2를 해킹하는 것이었습니다. PyIntObject의 필드를 long long 필드로 교체하고 sys.maxint의 값을 변경했습니다. 이 작업은 nulano’s branch of cpython에서 확인할 수 있습니다(다시 말하지만, 이것은 python2입니다).
이렇게 수정한 python을 이후 단계에서 사용했습니다. 이를 CPython64/64라고 부르겠습니다.
먼저 rpython/translator/c/test/에 있는 test_standalone.py와 test_newgc.py 같은 테스트가 CPython64/64 위에서 통과하도록 만들었습니다.
이것은 작은 변환을 실행하며, 일부 세부 사항이 잘못되어 있었습니다. 가장 명백한 것은 정수 타입 Signed를 다른 모든 플랫폼에서는 long과 같게 하되, Win64에서는 long long 같은 타입이 되어야 한다는 점입니다.
이어서 rpython/translator/c/src에 있는 모든 C 파일을 좀 더 전반적으로 검토하여, Win64에서도 32비트 정수를 뜻하는 long이라는 단어를 Signed로 바꾸었습니다.
그리고 이 두 C 타입에는 각각 대응하는 RPython 타입인 rffi.LONG과 lltype.Signed가 있습니다. 전자는 test_rffi_sizeof 테스트로 검증되듯이 실제로 C의 long에 대응해야 합니다. 후자의 크기는 rpython/rlib/rarithmetic에서 검증됩니다.
이러한 기본 테스트가 동작하게 된 후, 저희는 rpython/rlib/에서 rffi.LONG과 lltype.Signed가 각각 사용된 곳을 검토했습니다. 목표는 테스트를 고쳐서 LONG-versus-Signed 문제를 몇 가지 더 해결하는 것이었습니다 — 테스트는 언제나처럼 CPython64/64 위에서 실행했습니다. 참고로 일반 CPython에서 Win64용 테스트를 모두 실행하는 것을 목표로 rarithmetic에서 초기 작업이 일부 이루어졌지만, 이 초기 작업은 좋지 않은 발상으로 판단되어 중단되었습니다. CPython64/64만 살펴보십시오.
이것으로 --no-allworkingmodules로 시작하는 최소한의 모듈 구성에서 -O2 옵션을 사용해 PyPy를 변환하기에 충분했습니다. 이 변환을 실행할 때에도 CPython64/64를 사용했습니다. 마지막으로 C 컴파일러의 경고를 꼼꼼히 확인하자 손봐야 할 곳이 더 드러났습니다. MSVC는 기본적으로 정수 크기 불일치의 상당수를 오류가 아닌 경고로 보고합니다.
그런 다음 pypy/module/*/에서 LONG-versus-Signed 문제를 검토했습니다. 그 결과 모든 --translationmodules, 즉 변환을 실행하는 데 필요한 모든 것이 포함된, Windows 64에서 동작하는 변환된 PyPy를 얻었습니다. 이것을 얻고 나자 이후의 변환은 이 변환된 PyPy 위에서 실행할 수 있으므로, 해킹한 CPython64/64의 중요성은 크게 줄어들었습니다. 이 작업은 default 브랜치의 나이틀리 빌드에 반영되었으며, Win64에서 작업하려는 다른 모든 사람은 이것을 사용해야 합니다. 결국 전체 과정에는 기묘한 종류의 의존성이 생깁니다 — PyPy를 변환하려면 변환된 PyPy가 필요합니다 —. 하지만 Windows 실행 파일은 새로운 버전의 Windows에서도 절대 깨지지 않도록 되어 있으므로 여기서는 문제가 되지 않습니다.
즐겁게 해킹하십시오 :-)