2012-02-17 2 views
0

저는 지난 며칠 동안 CIL을 배우는 데 여유 시간을 보냈고 레이블 (br)과 메소드 (.method 선언)를 호출하는 것에 대한 분기에 대해 궁금합니다.코드를 CIL의 레이블 또는 함수로 호출합니까?

메서드를 선언하면 어셈블리 외부에서 액세스 할 수 있지만 개인 메서드 레이블을 만들고 br을 사용하여 분기하는 방법은 무엇인지 알고 있습니다. 거기에 성능 향상이 있습니까?

이 혼란을 정리하기 위해 여기에 (때문에 공간과 시간 제한) 단순화 된 예입니다

// calling code 
ldc.i4 5 
call int32 testmethod(int32) 
// other code 

// method 
.method public int32 testmethod(int32) 
{ 
    ldc.i4 10 
    add 
    ldc.i4 20 
    mul 
    ret 
} 

그래서 대신 그 방법을하고, 내가 할 수있는 라벨과 지사를 가지고 :

ldc.i4 5 
br testlabel 
leftoff: 
// remaining instructions 

testlabel: 
.lcd.i4 10 
add 
ldc.i4 20 
mul 
br leftoff 

그래서 메소드/레이블 testlabel은 int32를 취한 다음 10을 더하고 그 결과에 20을 곱합니다. 단점 (원래는 언급하지 않았 음)은 가독성이지만 컴파일러가 생성하면 가독성이 덜 중요하다는 사실을 알고 있습니다. 따라서 두 번째 예제를 사용하면 레이블을 사용하고 코드를 분기하여 성능 이점을 얻을 수 있습니까? 그렇지 않다면 짧은 지류에 맞출 수 있을까요? (br.s)

답변

2

설명하는 것은 기본적으로 메소드 인라인입니다. 방법은 여러 번 사용하는 경우

  • 그때는 아마 여러 번 인라인해야합니다 :이 방법을 인라인하면 성능을 향상시킬 가능성이 있지만,이 방법을 인라인하지 않도록 선택할 수있는 몇 가지 이유가있다 . 이로 인해 생성 된 IL의 크기가 전반적으로 증가 할 수 있으며 결과적으로 성능이 저하 될 수 있습니다.
  • 경우에 따라 메서드를 인라인 할 수 없습니다. 예를 들어 재귀 적 메서드는 인라인 될 수 없으며 (인라인 된 본문에서 무한대로 인라인 될 필요가 없으므로) 또한 가상 메서드 (호출 수신자의 런타임 유형을 알지 못한다고 가정) .
  • IL 작성시 메소드를 인라인하지 않더라도 어쨌든 기계 코드를 생성 할 때 JIT 컴파일러가 메소드를 인라인 할 수 있습니다.

UPDATE 당신의 구체적인 예를 주어

좋아는 제가 인라인을 참조하는 연결을 설명 할 수 있습니다. 메서드가 여러 번 호출되는 경우 (예 : testmethod을 두 번 연속 호출) 시뮬레이션 된 호출에 따라 다른 위치로 다시 분기해야하기 때문에 접근 방식이 작동하지 않지만 간단한 호출 방법은 없습니다. 로컬 변수를 추가하여 추가 상태를 추적 한 다음 조건부 분기를 사용할 수는 있지만 복잡한 경우에는 성능상의 이점을 취소 할 수 있습니다. 단 한 번만 호출되면 변환은 기본적으로 인라이닝과 같습니다. 단, 인라이닝 된 메소드와의 무조건 분기를 추가로 수행하는 경우는 예외입니다. 실제로 방법을 인라인하고 가지를 제거하는 것이 더 합리적이라고 생각합니다. 즉, 예를 들어 다음과 같이 나타납니다.

ldc.i4 5 
// start of inlined call to testmethod 
ldc.i4 10 
add 
ldc.i4 20 
mul 
// end of inlined call to testmethod 
// other code from caller goes here 

그런 다음 위의 인라이닝에 대한 위의 의견이 적용됩니다.

+0

재미있는 점은 메소드 인라이닝에 대한 이해가 전화 (또는 분기)를 작성하는 대신 코드가 기본적으로 호출이 이루어질 위치에 붙여 넣기된다는 점입니다. 당신은 여전히 ​​점프/가지의 오버 헤드를 가지고 있기 때문에 레이블은 어떻게할까요? 아니면 메소드 인라이닝에 대한 정의를 기반으로하지 않습니까? – Jetti

+0

@ 제티 - 글쎄, 나는 당신의 질문에서 외삽했다. 전화를 걸려는 사적인 방법으로 도약한다면, 일단 끝나면 어디로 돌아갈 지 어떻게 알 수 있습니까? 당신은 기본적으로이 메소드로 건너 뛰고 아마도 호출자에게로 돌아가고 싶습니다. 실제로 호출자에게로 건너 뛰기를 원할 것입니다. 이것은 실제로 라인에 있지 않다는 것을 제외하면 메소드를 인라이닝하는 것과 같습니다. – kvb

+0

그러나 여러 호출 사이트가있는 경우 여분의 상태를 추적하여 어디로 돌아갈 지 결정해야합니다 (또는 메소드를 여러 번 인라인해야 함). – kvb

관련 문제