' 호출 사이트 ' 컴파일러가 자동 코드를 생성합니까?

컴파일러에 의해 생성 된 일부 자동 코드 인 “호출 사이트”입니다.이 용어를 자주 접하고 호출 메서드를 단순히 “호출 사이트”라고하는 것처럼 들립니다. -말 그대로 괜찮아 보이지만 좀 더 복잡하다고 생각합니다. 그리고 “호출 사이트”가 컴파일러 생성 코드 인 경우-어떤 상황에서 이것이 필요합니까?

C # .Net의 맥락에서 이야기하고 있지만 이것은 표준 용어로 보입니다. 몇 가지 예를 통해 명확하고 정확한 설명을 주시면 감사하겠습니다.

댓글

  • 소스 코드와 자동에서 호출 사이트 개념이 있습니다. -생성 된 개체 코드.
  • C # 4 이상에서 동적 작업을 위해 호출 사이트가 생성되는 방식을 살펴볼 수 있습니다. 매우 흥미 롭습니다.
  • @EricLippert 감사합니다. 다행스럽게도 링크 를 찾았습니다. 여기서 매우 아름답게 설명하셨습니다. 그러나 통화 사이트 생성에 대해 구체적으로 설명하는 블로그를 찾을 수 없습니다.

답변

“전화 사이트 ”는 함수 또는 메서드가 호출되는 위치를 나타냅니다. 컴파일러 구성의 일반적인 용어이며 C #에만 국한되지 않습니다.

foo(); // call site void foo() { ... } // function definition 

호출 사이트는 특수 생성 된 코드가 아닙니다. 그러나 호출 사이트에서 컴파일러는 함수를 호출하는 명령을 내 보냅니다. 일반적으로 다음과 같습니다.

  • 현재 컨텍스트를 스택 프레임에 저장합니다.
  • 대상 함수의 호출 규칙에 따라 모든 인수를 저장합니다.
  • 메소드 디스패치가 필요할 수있는 대상 함수를 호출합니다.
  • 호출 규칙에 따라 반환 값을 검색합니다.
  • 스택 프레임에서 컨텍스트를 복원합니다.

메소드 디스패치는 실제로 호출해야하는 함수를 찾기 위해 복잡한 코드를 실행해야 할 수 있습니다. 이는 virtual 메서드, 특히 인터페이스를 통해 메서드를 호출 할 때 필요합니다. 완전한 메소드 디스패치 절차는 비용이 많이들 수 있습니다 (구현 된 인터페이스 수에서 O (n) 또는 사용 가능한 메소드 수에서 O (n)). 그러나 대부분 (일반적으로 70–90 %) 호출 사이트에는 동일한 유형의 개체가 표시됩니다. 그런 다음 메서드 조회 결과를 캐시하는 것이 좋습니다. 그런 다음 컴파일러는 호출 사이트에서 다음과 같은 코드를 생성 할 수 있습니다.

static lastType = null; static lastMethod = null; if (type(instance) != lastType) { lastType = type(instance); lastMethod = performMethodLookup(instance, methodName); } result = lastMethod(instance, args); 

이를 모노 모픽 라고합니다. 인라인 캐시 . .NET CLR은 Virtual Stub Dispatch 라는 약간 더 복잡한 접근 방식을 개발했습니다. 호출 사이트에서 디스패치를 수행하는 대신 런타임 JIT는 스텁 메서드를 컴파일합니다. 전체 메소드 디스패치 프로 시저를 수행하고 캐시 된 메소드를 사용하기위한 다른 스텁이 있습니다. 호출 사이트에서는 스텁에 대한 호출 만 있고 스텁은 호출을 실제 대상으로 전달합니다. 이 호출 사이트의 통계에 따라 호출 사이트의 기계어 코드가 다른 스텁을 사용하도록 패치됩니다.

Answer

호출 사이트의 가장 일반적인 용도는 아마도 현재 Wikipedia에 선언 된 일 것입니다. 이것은 일부 코드에서 함수 또는 서브 루틴이 만들어집니다. 모든 언어에 적용 할 수있는 완전히 일반적인 용어입니다 (동적 프로그래밍과는 전혀 관련이 없습니다!).


저는 일반적으로 사용되는 용어를 듣습니다 (단지 용어 “호출”) 호출의 기본 의미론 또는 함수 / 메소드 정의의 의미와는 반대로 함수 / 메서드 / 서브 루틴이 호출되는 코드의 구문과 의미를 논의하고 있음을 명확히합니다. 이런 식으로 컴파일러 나 생성 코드에 대해서는 절대 아닙니다 (아몬이 이미 논의했듯이 컴파일러 / 런타임에 의해 생성 된 코드에이 용어가 여전히 적용 되더라도). 호출로 해석되는 특정 코드를 컨텍스트로 가져오고 때로는 바로 근처에있는 코드를 가져 오는 것에 대해 설명합니다.

이것이 제가 머릿속에있는 일종의 그림입니다.

 call-site call call-target/method definition --> --> int.TryParse(str, out i); (runtime) public static bool TryPars(... 

“call-site “는 호출 구문과 호출자에게 영향을 미치는 의미 (amon에 의해 자세히 설명 됨)에 대해 이야기 할 때 유용한 용어입니다. 예를 들어 C #의 새로운 in 수정 자, “in”으로 인수를 전달하는 “호출”은 이와 관련된 특정 의미를 가지고 있습니다 (참고로 전달됩니다. 사본), 그러나 “”호출 사이트에서 “구문에서 반드시 명확하지는 않습니다. 여기서 in는 필수가 아닙니다. 아이디어는 in를 사용하여 참조로 인수를 전달하는 호출 사이트 의미 (즉, 호출자 / 호출 사이트에 영향을주는 동작)가 가깝다는 것입니다. 호출 사이트에서 구문으로 명확화 할 필요가없는 값으로 전달하는 것만 큼 충분합니다.나는이 주장에 동의하지 않습니다. “call-site”와 같은 용어없이 논의하기가 어려울 것입니다!

또 다른 예 : 동적 호출 (예 : 가상 / 인터페이스 방법)은 다소 복잡한 런타임 동작 (다시 말하지만, amon에 의해 자세히 설명 됨) 및 “컴파일시 어떤 메서드가 호출 될지 알 수 없지만”호출 사이트 “가 신경 쓰는 모든 것은 해당 호출을 디스패치하는 의미입니다.

object의 경우 실제로 string 정말 신경 쓰지 않습니다.

호출 사이트에서, object가 가상 ToString() 메소드를 노출하는 것만 신경 쓰게됩니다 (런타임까지 실제로 호출 할 메서드를 결정합니다). 실제로 호출 사이트 (예 : C #)에서 이것이 가상 호출인지 여부가 구문에서 반드시 명확하지는 않습니다. 가상 호출과 가상 호출이 아닌 호출 사이의 구분은 호출시 충분히 중요하지 않은 것으로 간주됩니다. (컴파일러 / 런타임이 의미있는 호출을하는 것이 매우 중요하더라도) 호출 사이트 에서 프로그래머를 위해 명확화 할 필요가없는 사이트 >

마지막 예 : C # “s ref 및 C ++”s & : 둘 다 호출 사이트의 의미 체계 언어는 두 언어에서 거의 동일합니다. 값이 아닌 참조가 전달되지만 각 언어는 호출 사이트에서 다른 구문을 가지고 있습니다. 여기서 C #은 ref를 요구하고 C ++는 그렇지 않습니다. & (또는 이와 유사한 것)이 필요합니다. 다시 말하지만, 언어 설계자는 호출 사이트의 의미 체계에 의해 정보를 받아 호출 사이트에서 호출이 표현되는 방식에 대한 몇 가지 구문 결정을 내 렸습니다. (저는 호출 사이트 의미를 노출하기 때문에 C # 호출 사이트 구문을 선호하는데, 프로그래머로서 제가 그러한 호출을 할 때 인정해야한다고 생각합니다). 메소드 정의는 매개 변수를 수정하는 동작을 변경하기 때문에 참조로 매개 변수를 수신하고 있음을 알아야한다는 사실이 분명합니다 (예 : = 사용). 그러나 런타임이 신경 쓰지 않는다 (런타임 디스패치가 명목상 정보를받는 정적으로 형식화 된 언어에서) : 호출자로부터 피 호출자에게이 값을 가져 오면됩니다. , 참조인지 아닌지 상관하지 않습니다. 이는 호출 사이트 및 호출 대상에 대한 문제입니다.


좀 더 느슨하게 “호출 사이트”는 호출을 나타내는 코드와 그 주변의 “관련”코드 (단지 “호출”이 아님). 예를 들어 C #에서 호출 사이트 “에”더미 변수를 정의하는 것을 참조 할 수 있습니다. TryParse 메서드를 호출하는 경우 :

int dummy; bool looksLikeAnInt = int.TryParse(str, out dummy); 

이 전체 “블록”은 호출 사이트의 일부로 간주 될 수 있습니다. 나는 이것이 덜 “정확한”의미라고 생각하지만 그것이 사용을 멈추게하지 않습니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다