툰크

Thunk

컴퓨터 프로그래밍에서 thunk는 다른 서브루틴에 계산을 주입하는 데 사용되는 서브루틴이다.Thunk는 주로 결과가 필요할 때까지 계산을 지연하거나 다른 서브루틴의 시작 또는 끝에 작업을 삽입하는 데 사용된다.그들은 컴파일러 코드 생성모듈 프로그래밍에 다른 많은 응용 프로그램을 가지고 있다.

이 용어는 동사가 생각하는 변칙적인 형태에서 유래되었다.ALGOL 60 컴파일러에서 Thunk를 원래 사용한 것을 말하며, 어떤 유형의 루틴을 생성해야 할지를 결정하기 위해 특별한 분석(생각)이 필요했다.[1][2]

배경

컴파일러 연구의 초창기에는 서로 다른 평가 전략을 사용한 광범위한 실험이 있었다.핵심 질문은 인수가 상수가 아닌 임의의 수학 식일 수 있는 경우 서브루틴 호출을 어떻게 컴파일하느냐 하는 것이었다."call by value"라고 알려진 한 접근방식은 통화 전 모든 인수를 계산한 다음 결과 값을 서브루틴으로 전달한다.경쟁 상대인 "이름별 호출" 접근법에서 서브루틴은 평가되지 않은 논쟁 표현을 받아 평가해야 한다.

"이름별 호출"의 간단한 구현은 서브루틴에 있는 해당 파라미터의 각각의 모양에 대해 인수 표현식의 코드를 대체할 수 있지만, 이것은 서브루틴의 여러 버전과 표현식 코드의 여러 복사본을 생성할 수 있다.개선사항으로 컴파일러는 인수의 값을 계산하는 Thunk라고 불리는 도우미 서브루틴을 생성할 수 있다.그런 다음 이 도우미 서브루틴의 주소와 환경이[a] 원래의 주장 대신 원래의 서브루틴으로 전달되며, 여기서 필요한 횟수만큼 호출할 수 있다.피터 인게르만은 먼저 호별 평가를 지원하는 ALGOL 60 프로그래밍 언어와 관련하여 thunks를 설명했다.[4]

적용들

기능 프로그래밍

소프트웨어 산업은 대체로 가치별 통화 및 기준별 평가로 표준화되었지만, 기능 프로그래밍 커뮤니티에서는 호별 통화에 대한 활발한 연구가 계속되었다.[5]이 연구는 일련의 게으른 평가 프로그래밍 언어를 만들어 냈는데, 이 언어들은 이름별 호칭의 일부 변종이 표준 평가 전략이다.Glasgow Haskell Compiler와 같은 이러한 언어의 컴파일러는 thunk에 크게 의존해 왔으며, thunk들이 초기 결과를 저장하여 다시 계산하는 것을 피할 수 있다는 추가적인 특징을 가지고 있다;[6] 이것은 메모화 또는 콜바이 니즈라고 알려져 있다.

기능적 프로그래밍 언어는 프로그래머들이 명시적으로 thunk를 생성하도록 허용했다.이것은 자체의 매개변수가 없는 익명 함수로 인수 식을 감싸서 소스 코드로 이루어진다.이는 수신함수가 익명함수를 호출할 때까지 표현이 평가되는 것을 방지하여 호별호출과 같은 효과를 얻는다.[7]익명 기능을 다른 프로그래밍 언어로 채택함으로써 이 기능을 널리 이용할 수 있게 되었다.

다음은 자바스크립트(ES6)의 간단한 시연이다.

// 'hypot'은 이진함수 경시하다 하이픈을 치다 = (x, y) => 수학.sqrt(x * x + y * y);  // 'thunk'는 인수를 사용하지 않고, 호출될 경우 잠재적으로 비용이 많이 드는 기능을 수행하는 기능이다. // 연산(이 예에서는 제곱근으로 표시) 및/또는 일부 부작용 발생 경시하다 쿵쿵 울리다 = () => 하이픈을 치다(3, 4);  // thunk를 평가받지 않고 전달할 수 있음... doSomethingWith툰크(쿵쿵 울리다);  // ...또는 평가됨 쿵쿵 울리다(); // === 5 

객체 지향 프로그래밍

Thunk는 클래스여러 인터페이스를 상속할 수 있도록 하는 객체 지향 프로그래밍 플랫폼에서 유용하며, 여러 인터페이스를 통해 동일한 방법을 호출할 수 있는 상황을 초래한다.다음 코드는 그러한 상황을 C++로 설명한다.

계급 A {  공중의:   가상의 인트로 접근() 경시하다 { 돌아오다 value_; }   사유의:   인트로 value_; };  계급 B {  공중의:   가상의 인트로 접근() 경시하다 { 돌아오다 value_; }   사유의:   인트로 value_; };  계급 C : 공중의 A, 공중의 B {  공중의:   인트로 접근() 경시하다 무효로 하다 { 돌아오다 better_value_; }   사유의:   인트로 better_value_; };  인트로 사용하다(B *b) { 돌아오다 b->접근(); }  인트로 본래의() {   // ...   B some_b;   사용하다(&some_b);   C some_c;   사용하다(&some_c); } 

이 예에서 각 등급 A, B, C에 대해 생성된 코드는 호출에 사용할 수 있는 디스패치 테이블을 포함할 것이다.Access동일한 유형의 참조를 통해 해당 유형의 개체에 대해.클래스 C에는 호출에 사용되는 추가 디스패치 테이블이 있음AccessB형의 참조를 통해 C형의 물체에 대하여.그 표현b->Access()b가 참조하는 대상의 종류에 따라 B의 자체 디스패치 테이블이나 추가 C 테이블을 사용한다.C형 물체를 가리킬 경우 컴파일러는 C형 물체를 확인해야 한다.Access구현은 해당 개체의 상속된 B 부분이 아닌 전체 C 개체의 인스턴스 주소를 수신한다.[8]

이 포인터 조정 문제에 대한 직접적인 접근 방법으로서, 컴파일러는 각 디스패치 테이블 항목에 정수 오프셋을 포함할 수 있다.이 오프셋은 기준의 주소와 방법 구현에 필요한 주소 간의 차이점이다.그런 다음 이 디스패치 테이블을 통해 각 호출에 대해 생성된 코드는 오프셋을 검색하고 메서드를 호출하기 전에 인스턴스 주소를 조정하는 데 사용해야 한다.

방금 설명한 해결책은 앞에서 설명한 호별 호칭의 순전한 구현과 유사한 문제를 가지고 있다. 컴파일러는 인수를 계산하기 위해 여러 개의 코드 복사본을 생성하는 동시에 오프셋을 유지하기 위해 디스패치 테이블 크기를 증가시킨다.그 대안으로 컴파일러는 C의 구현과 함께 조정자 thunk를 생성할 수 있다.Access필요한 양만큼 인스턴스 주소를 조정하고 메소드를 호출한다.B를 위한 C의 발송표에 Thunk가 나타날 수 있으므로, 발신자가 직접 주소를 조정할 필요가 없다.[9]

여러 지점에서 평가가 필요한 수치 계산

통합과 같은 계산을 위한 루틴은 여러 지점에서 식을 계산해야 한다.폐쇄절차 매개변수를 지원하지 않는 언어에서는 이름별 호출을 이 목적으로 사용했다.

상호운용성

Thunk는 루틴이 서로 직접 호출할 수 없는 소프트웨어 모듈 간의 상호운용성을 제공하기 위해 널리 사용되어 왔다.이는 루틴이 서로 다른 호출 규칙을 가지고 있거나, CPU 모드나 주소 공간이 서로 다르거나, 가상 시스템에서 하나 이상의 실행이 있기 때문에 발생할 수 있다.컴파일러(또는 다른 도구)는 인수를 변환하거나 다른 위치로 복사하거나 CPU 모드를 전환하든, 대상 루틴을 호출하는 데 필요한 추가 단계를 자동화하는 thunk를 생성하여 이 문제를 해결할 수 있다.쾅이 성공하면 일반 통화에 비해 발신자가 해야 하는 추가 작업을 최소화할 수 있다.

상호운용성에 관한 많은 문헌은 MS-DOS,[10] OS/2, Windows[11][12][13][14] 를 포함한 다양한 Wintel 플랫폼과 관련이 있다.NET 및 16비트 메모리 주소 지정에서 32비트 메모리 주소로 전환.고객이 플랫폼 간에 이동함에 따라 이전 플랫폼용으로 작성된 기존 소프트웨어를 지원하기 위해 Thunk가 필수적이었습니다.

x86의 32비트 코드에서 64비트 코드로의 전환도 Thunking(WoW64)의 형태를 사용한다.그러나, x86-64 주소 공간이 32비트 코드에 사용할 수 있는 주소 공간보다 크기 때문에, 기존의 "일반 꽝" 메커니즘을 사용하여 32비트 코드의 64비트 코드를 호출할 수 없었다.[15]32비트 코드가 64비트 코드를 호출하는 유일한 경우는 WoW64가 Windows API를 32비트로 스컹크하는 경우뿐이다.

오버레이 및 동적 연결

자동 가상 메모리 하드웨어가 없는 시스템에서 thunk는 오버레이라고 알려진 제한된 형태의 가상 메모리를 구현할 수 있다.오버레이를 사용하여 개발자는 프로그램의 코드를 독립적으로 로드하고 언로드할 수 있는 세그먼트로 나누고 각 세그먼트의 진입점을 식별한다.다른 세그먼트로 호출되는 세그먼트는 분기 테이블을 통해 간접적으로 호출해야 한다.세그먼트가 메모리에 있으면 분기 테이블 항목이 세그먼트로 점프한다.세그먼트가 언로드되면 해당 항목은 요청 시 다시 로드할 수 있는 "재로드 thunk"로 대체된다.[16]

마찬가지로 런타임에 프로그램의 모듈을 함께 동적으로 연결하는 시스템도 thunks를 사용하여 모듈을 연결할 수 있다.각 모듈은 모듈을 로드할 때 링커가 채워지는 툰 테이블을 통해 다른 모듈들을 호출할 수 있다.이렇게 해서 모듈이 메모리에 있는 위치에 대한 사전 지식 없이 상호작용을 할 수 있다.[17]

참고 항목

Thunk 기술

관련개념

메모들

  1. ^ Thunk는 초기 제한적인 형태의 폐쇄다.thunk에게 전달된 환경은 표현된 표현이지, 호출된 일상적 표현은 아니다.[3]

참조

  1. ^ 에릭 레이몬드는 "이 용어의 기원에 대해 떠도는 두어 가지 의학적 신화"를 거부하고, "알골-60의 논쟁의 유형을 조금의 정리된 시간적 생각만으로 미리 알아낼 수 있다는 것을 (토론시간 후 몇 시간 후) 깨달은 후에 만들어진 말"이라는 말을 떠올리며 깡패의 발명가를 인용한다 [...] 나는다시 말해서, 그것은 '생각되어졌다'; 따라서 그것은 '아침 두 시에 '생각'의 과거 시제'인 깡충이라는 이름으로 명명되었다.참조:Raymond, Eric S. (1996). Raymond, Eric S. (ed.). The New Hacker's Dictionary. MIT Press. p. 445. ISBN 9780262680929. Retrieved 2015-05-25.
  2. ^ 인게르만(1961년) 참조 : "번역자는 실제 매개변수의 형성과 이전에 스캔한 선언의 형성을 고려함으로써 어떤 종류의 꽝을 만들어야 하는지 알고 있다…[W]절차 선언이 편찬되고 있는데, 번역자는 다시 구문을 관찰함으로써, 깡패에게 어떤 종류의 주소를 기대해야 할지 알고 있다."
  3. ^ E. T. Irons (1961-01-01). "Comments on the Implementation of Recursive Procedures and Blocks in ALGOL". Communications of the ACM. Association for Computing Machinery (ACM). 4 (1): 65–69. doi:10.1145/366062.366084. ISSN 0001-0782.
  4. ^ Ingerman, P. Z. (1961-01-01). "Thunks: a way of compiling procedure statements with some comments on procedure declarations". Communications of the ACM. Association for Computing Machinery (ACM). 4 (1): 55–58. doi:10.1145/366062.366084. ISSN 0001-0782.
  5. ^ Scott, Michael (2009). Programming Language Pragmatics. p. 395.
  6. ^ Marlow, Simon (2013). Parallel and Concurrent Programming in Haskell. p. 10.
  7. ^ Queinnec, Christian (2003). Lisp in Small Pieces. p. 176.
  8. ^ Stroustrup, Bjarne (Fall 1989). "Multiple Inheritance for C++" (PDF). Computing Systems. USENIX. 1 (4). Retrieved 2014-08-04.
  9. ^ Driesen, Karel; Hölzle, Urs (1996). "The Direct Cost of Virtual Function Calls in C++" (PDF). OOPSLA. Retrieved 2011-02-24. {{cite journal}}:Cite 저널은 필요로 한다. journal=(도움말)
  10. ^ Calcote, John (May 1995). "Thunking: Using 16-Bit Libraries in OS/2 2.0". OS/2 Developer Magazine. 7 (3): 48–56.
  11. ^ King, Adrian (1994). Inside Microsoft Windows 95 (2nd ed.). Redmond, Washington, USA: Microsoft Press. ISBN 1-55615-626-X.
  12. ^ Programmer's Guide to Microsoft Windows 95: Key Topics on Programming for Windows from the Microsoft Windows Development Team. Technical Reference (1st ed.). Redmond, Washington, USA: Microsoft Press. 1995-07-01. ISBN 1-55615-834-3. Retrieved 2016-05-26.
  13. ^ Hazzah, Karen (1997). Writing Windows VxDs and Device Drivers - Programming Secrets for Virtual Device Drivers (2nd printing, 2nd ed.). Lawrence, Kansas, USA: R&D Books / Miller Freeman, Inc. ISBN 0-87930-438-3.
  14. ^ Kauler, Barry (August 1997). Windows Assembly Language and Systems Programming - 16- and 32-Bit Low-Level Programming for the PC and Windows (2nd ed.). Lawrence, Kansas, USA: R&D Books / Miller Freeman, Inc. ISBN 0-87930-474-X.
  15. ^ "Why can't you thunk between 32-bit and 64-bit Windows?". The Old New Thing. 2008-10-20.
  16. ^ Bright, Walter (1990-07-01). "Virtual Memory For 640K DOS". Dr. Dobb's Journal. Retrieved 2014-03-06.
  17. ^ Levine, John R. (2000) [October 1999]. Linkers and Loaders. The Morgan Kaufmann Series in Software Engineering and Programming (1 ed.). San Francisco, USA: Morgan Kaufmann. ISBN 1-55860-496-0. OCLC 42413382. ISBN 978-1-55860-496-4. Archived from the original on 2012-12-05. Retrieved 2020-01-12. 코드: [1][2] 에라타: [3]