2009-12-15 5 views
1

나는 일종의 일리노이 주인이 아니다. 나는 가끔씩 컴파일러가 작성한 코드를 확인하기 위해 그것을 사용한다. 내가 궁금해했던 한 가지는 왜 .maxstack이 때때로 얻는 가치를 얻는가하는 것입니다. 다음 클래스 고려 : 다음참조를 저장하지 않을 때 더 큰 .maxstack?

public class Sample 
{ 
    public void SomeMethod(){} 
} 

을, 나는 프로그램과 같이이 다음과 같은 경우에 지금

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  13 (0xd) 
    .maxstack 1 
    .locals init ([0] class ConsoleApplication1.Sample sample) 
    IL_0000: newobj  instance void ConsoleApplication1.Sample::.ctor() 
    IL_0005: stloc.0 
    IL_0006: ldloc.0 
    IL_0007: callvirt instance void ConsoleApplication1.Sample::SomeMethod() 
    IL_000c: ret 
} // end of method Program::Main 

:

private static void Main(string[] args) 
{ 
    Sample sample = new Sample(); 
    sample.SomeMethod();  
} 

위의 코드는 다음과 IL (컴파일 된 릴리스를) 제공 프로그램 코드를 다음과 같이 변경합니다.

private static void Main(string[] args) 
{ 
    new Sample().SomeMethod(); 
} 

... 그것은 다음 IL 코드 결과

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  11 (0xb) 
    .maxstack 8 
    IL_0000: newobj  instance void ConsoleApplication1.Sample::.ctor() 
    IL_0005: call  instance void ConsoleApplication1.Sample::SomeMethod() 
    IL_000a: ret 
} // end of method Program::Main 

번째 IL 코드가 예상되는 짧다. 하지만 조금 호기심이 생기는 이유는 .maxstack 8 번째 코드 샘플에서는 8 번이지만 첫 번째 코드 샘플에서는 1 번입니까? 왜 두 번째 코드가 시스템을 작동시켜 더 큰 스택을 확보하게됩니까?

+0

디버그 모드입니까, 릴리스 모드입니까? 나는 stdloc.0과 ldloc.0의 필요성이 디버깅을 쉽게하는 것 이외에 무엇인지 궁금하다. –

+0

@Cecil : 그것은 릴리스되었습니다 (텍스트에 묻혀 있지만 질문에 명시된대로). –

답변

4

메소드 헤더의 2 진 표현은 "작은 형식"과 "뚱뚱한 형식"을 갖습니다. 작은 헤더 바이트 수가 소요 한 다음 조건이 충족 될 때 사용될 수있다 :

  • 맥스 < = 8
  • 예외 처리
  • 로컬 변수
  • 코드 크기 < 64 바이트 스택

변경 사항으로 인해 컴파일러는이 양식을 사용할 수 있었고, 작은 헤더가 발견되면 항상 최대 스택 8 개를 사용한다고 가정합니다.

나에게 특별한 관심의 보조 노트에

Reference is ECMA-335 §25.4.2

합니다 (영업 이익 메모 당) 릴리스 빌드에 그들이 단축 형태가 모두 작고 빠른 서로 다른 코드를 생성한다는 사실이다. 어떤 버전의 C#을 사용하고 있습니까? 이후 버전에서는이 명백한 최적화를 활용할 것으로 기대합니다.

  • 의미를 변경하지 않고 로컬 변수를 제거 할 수 있습니다.
  • 로컬 변수가없는 경우 컴파일러는 값의 구체적인 유형이 정확히 Sample임을 알고 있으므로 SomeMethod이 가상 인 경우에도 call 명령어로 직접 호출 할 수 있습니다.
관련 문제