라벨이 PyPy인 게시물 표시

Python은 어떻게 swap하는가

  지난번 글 에서 Lua의 multiple assignment를 이용한 swap이 내부적으로 어떻게 돌아가는지 설명했었다. 그렇다면 파이선은 어떨까?  자신의 버추얼 머신의 구현까지 제공하는 루아와 다르게 파이선은 공식적으로 어떤 버추얼 머신을 사용해야 하는지 제공하지 않는다. dis 라이브러리를 통해서 어떤 바이트 코드가 나오는지 알 수 있지만, 구체적인 버추얼 머신의 스펙을 정의하거나 바이트 코드의 구현을 정의하지 않는다. 덕분에 PyPy , IronPython , Jython 등 다양한 구현체가 존재한다. 이번에는 우선 그중에서 사실상 표준 구현체라고 할 수 있는 CPython의 구현에 대해서 살펴보겠다.  CPython의 버추얼 머신이 어떻게 구현돼야 하는가는 명확히 기술되지 않았지만, CPython의 바이트 코드를 보면, CPython은 Lua가 레지스터 머신을 사용하는 것과 다르게 스택 머신을 사용한다는 것을 쉽게 알 수 있다. CPython의 버추얼 머신은 스택과 글로벌/로컬 메모리를 가지고 있다. 글로벌 메모리와 로컬 메모리는 객체의 레퍼런스를 저장하는 데 사용되고 계산을 하기 위해서는 스택으로 레퍼런스를 복사해온 뒤 사용해야 한다.  이제 swap이 CPython에서 어떤 바이트 코드로 컴파일되는지 살펴보자.  위와 같은 코드는 아래와 같은 바이트 코드로 컴파일된다.  여기서 ROT_TWO 는 스택의 가장 위의 두 아이템의 위치를 바꿔주는 바이트 코드다. 즉, 위의 바이트 코드는 스택에 a 를 올리고 b 를 올린 뒤, 스택의 가장 위의 두 아이템의 위치를 바꾸고, 스택 가장 위의 아이템을 b 에 다음 아이템을 a 에 저장하는 것이다.  그렇다면 ROT_TWO 는 어떻게 구현됐을까? 현재 CPython에서 ROT_TWO 는 임시 변수 2개를 사용하여 스택의 두 값의 위치를 바꾸는 것으로 돼 있다. 즉, CPython에서는 변수 2개를 스왑하기 위해서 스택의 두 자리, ROT_TWO 에서 사용하는 임시 변수 두 자리까지 총