2014-11-20 1 views
13

그래서 I've read many times before 기술적으로 .NET 이 그것의 연산 코드를 가지고 있기 때문에 TCO (tail call optimization)를 지원하고 C#은이를 생성하지 않기 때문에.꼬리 호출 최적화에 op 코드가 필요한 이유는 무엇입니까?

나는 TCO가 왜 opcode를 필요로하는지 또는 어떻게해야하는지 정확히 알지 못합니다. 내가 아는 한, TCO를 수행 할 수있는 요구 사항은 재귀 호출의 결과가 현재 함수 범위의 변수와 결합되지 않는다는 것입니다. 만약 당신이 그것을 가지고 있지 않다면, opcode가 스택 프레임을 열어 두지 않아도되는 것을 보지 못합니다. 만약 당신이 그렇게한다면, 컴파일러는 언제나 그것을 반복적으로 쉽게 컴파일 할 수 없을까?

그래서 opcode의 요점은 무엇입니까? 분명히 내가 빠진 것이있다. TCO가 전혀 가능하지 않은 경우, opcode 레벨보다 항상 컴파일러 레벨에서 처리 할 수 ​​있습니까? 그것이 할 수없는 곳의 예는 무엇입니까?

+2

이 opcode는 높은 수준의 컴파일러에서 JITter에 이르는 힌트와 같아서 나중에는 핵심 기능 중 하나 인 빠른 컴파일이 가능한 잠재적 인 시간에서 벗어날 수 있습니다. 어떤 시나리오에서 테일 콜 최적화가 실제로 가능한지 확인하기 위해 일리노이 분석 작업을 수행합니다. –

답변

8

,이


Source

> CLR을하고 꼬리는

를 호출 .. 꽤 밀접하게 질문에 대한 대답 나에게 보이는 부분이다

CLR에서 관리하는 언어 인 을 처리 할 때 두 개의 ki 재생중인 컴파일러의 수는입니다. 여러분의 언어 소스 코드에서 IL (C# 개발자는 csc.exe라고 알고 있습니다.), 그리고 IL에서 네이티브 코드 (런타임에 호출되는 JIT 32/64 비트 컴파일러)로가는 컴파일러가 있습니다. 또는 NGEN 시간). 소스 -> IL 및 IL-> 원시 컴파일러 모두 테일 호 최적화를 이해합니다. 그러나 IL-> 네이티브 컴파일러 (JIT라고 부름)에는 테일 콜 최적화가 궁극적으로 사용될 것인지 여부에 대한 최종 의견이 있습니다. 소스 -> IL 컴파일러는 "꼬리"사용을 포함하여 꼬리 호출을하는 데 도움이되는 IL을 생성하는 데 도움이 될 수 있습니다. 일리노이 접두사 (자세한 내용은 나중에 설명합니다). 이런 식으로 소스 -> IL 컴파일러는 JIT가 테일 호출을하도록 설득하기 위해 생성하는 IL을 구조화 할 수 있습니다. 그러나 JIT에는 항상 원하는대로 수행 할 수있는 옵션이 있습니다.

언제 꼬리표를 호출합니까?

나는 다양한 JIT가 꼬리 호출 최적화를 어떤 조건에서 사용하는지에 따라 JIT에서 일하는 일을 한 나에게서 홀의 Fei Chen과 Grant Richins에게 물었다. 완전한 대답은 오히려 상세합니다. 빠른 요약은 JIT가 가능한 한 언제든지 꼬리 호출 최적화를 사용하려고하지만 꼬리 호출 최적화를 사용할 수없는 많은 이유가 있다는 것입니다.꼬리 호출은 옵션이 아닌 이유 몇 가지 이유 :

    발신자 발신자와 수신자 사이의
  • 스택 인수가하고자하는 방식으로 호환되지 않는 (:-) 대만족) 호출 후 즉시 반환하지 않습니다
  • 우리는 (인라인 꼬리 호출하는 것보다 더 나은 방법이며, 더 많은 최적화에 문을 엽니 다) 대신 전화를 인라인
  • 을 다른 종류의
  • 발신자를 실행하고 수신자 반환 할 수있는 수신자하기 전에 발신자의 프레임에 주위에 물건을 이동이 필요
  • 보안 디버거/프로파일 러는 JIT 최적화를

사이에, 내 생각에 그것은 매우 분명하게 질문의 맥락에서 가장 흥미로운 부분을 해제하는 방식

  • 에 도착 많은 시나리오는 입니다. 위에 언급 된 보안 예 ...

    많은 경우에 .NET의 보안은 정확한 스택에 달려 있습니다 ... 런타임에서 .. 위에서 강조한 바와 같이, CIL 컴파일러 소스와 (런타임) CIL- 네이티브 JIT 컴파일러 모두에서 부담을 공유하고 마지막 컴파일러는 최종 컴파일러와 공유됩니다.

  • +0

    하지만 꼬리 opcode가 필요한 이유는 무엇입니까? JIT는 항상 TCO를 시도 할 수 있습니다. – usr

    1

    추측 : "수동으로"스택을 관리하는 x86 어셈블러와 같은 간단한 언어에서는 opcode가 필요하지 않습니다. 호출 스택을 적절하게 설정할 수 있습니다.

    그러나 .NET CIL과 같이 더 높은 수준에서 스택은 부분적으로 관리되며 함수를 호출하는 전체 동작은 단일 opcode (예 : 호출)입니다. 따라서 TCO를 구현하려면 다른 opcode가 필요합니다.이 기능은 "이 기능에 제어 흐름을 전달하지만 새 스택 프레임을 만들지 않습니다." 이미 제공된 링크 다음

    관련 문제