64비트 PyPy와 Windows¶
64비트 윈도우가 PyPy에서 동작하도록 만드는 것은 오랫동안 이어진 요청이었고, 여러모로 저주받은 해였던 2020년에 마침내 해결되었습니다. 문제는 RPython의 정수 타입(rffi.SIGNED)이 정수로 형변환된 포인터 값을 (가끔) 담을 수 있을 만큼 충분히 크다고 가정한다는 데 있습니다. 대부분의 플랫폼에서는 이에 대응하는 C 타입인 long이 이 조건을 만족합니다. 하지만 64비트 윈도우에서는 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는 정수가 long으로 변환되기 전까지 sys.maxint의 더 큰 값까지 지원합니다.
저희가 한 일¶
가장 먼저 한 일은 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 위에서 통과하도록 만들어졌습니다.
이것은 작은 번역(translation)들을 실행하며, 일부 세부 사항이 잘못되었습니다. 가장 명백한 것은 다른 모든 플랫폼에서는 정수 타입 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에서 검증됩니다.
이러한 기본 테스트가 통과한 후, 저희는 rffi.LONG과 lltype.Signed의 사용을 비교하기 위해 rpython/rlib/를 검토했습니다. 목표는 항상 CPython64/64 위에서 실행되는 테스트들을 고쳐서 LONG-versus-Signed 문제를 좀 더 해결하는 것이었습니다. rarithmetic에서 일반 CPython의 Win64 환경에서 모든 테스트를 실행하는 것을 목표로 초기 작업이 이루어졌지만, 이 초기 작업은 나쁜 아이디어로 판단되어 포기되었다는 점에 유의하십시오. CPython64/64만 살펴보십시오.
이는 최소한의 모듈 집합으로 -O2를 사용해 PyPy의 변환을 얻기에 충분했으며, --no-allworkingmodules로 시작했고, 이 변환을 실행하는 데에도 CPython64/64를 사용했습니다. 마지막에 C 컴파일러의 경고를 꼼꼼히 확인해보니 작업이 더 필요한 부분이 드러났습니다. 기본적으로 MSVC는 정수 크기 불일치 대부분을 오류가 아닌 경고로 보고합니다.
그런 다음 우리는 LONG-versus-Signed 문제를 위해 pypy/module/*/를 검토했습니다. 이를 통해 모든 --translationmodules를 포함하는, 즉 번역(translation)을 실행하는 데 필요한 모든 것을 포함하는 Windows 64용 작동하는 번역된 PyPy를 얻었습니다. 일단 이것이 갖춰지자, 수정된 CPython64/64는 훨씬 덜 중요해졌는데, 이는 이 번역된 PyPy 위에서 향후 번역(translation)을 실행할 수 있기 때문입니다. 이는 default 브랜치의 야간 빌드에 반영되었으며, Win64에서 작업하려는 다른 모든 사람이 사용해야 합니다. 전체 과정은 결국 이상한 종류의 의존성으로 귀결됩니다 — PyPy를 번역(translation)하려면 번역된 PyPy가 필요합니다 — 하지만 Windows 실행 파일은 새로운 버전의 Windows에서도 절대 깨지지 않아야 하므로, 여기서는 문제없습니다.
즐거운 해킹 되세요 :-)