2016-12-09 2 views
2

Go에서는 최근에 특정 기능과 관련하여 "컨텍스트 레지스터"구현에 대한 의견이 있음을 확인했습니다. 컨텍스트 레지스터 란 무엇이며 Go 코드가 컴파일되는 방식을 어떻게 변경합니까?golang의 컨텍스트 레지스터 란 무엇입니까?

배경 : GOROOT의 일부 (예 : reflect)에서 스텁 함수의 사용을 보았지만 어떻게 작동하는지 잘 모르겠습니다.

+2

"컨텍스트 레지스터"는 Go 작성자가 클로저의 컨텍스트를 유지하는 레지스터를 호출 한 것입니다. 스텁 함수 (어셈블리 파일, 런타임 등)는 실제로 관련되지 않습니다. 그리고 네, 이에 대해 질문이 있으시면 메일 링리스트는 훨씬 더 적절한 포럼입니다. – JimB

+1

잘만되면이 메타는 아니지만 왜 stackoverflow입니까? 전자 메일 목록보다 go-lang 질문에 대해 "그다지 적합하지 않은"것을 완전히 목적으로 프로그래밍 질문에 답변하는 사이트입니까? – eje

+2

@eje : 가장 좋은 이유는 gc 툴체인의 구현 세부 사항에 대한 답변을 원한다면 메일 링리스트가 더 나은 포럼이라는 것입니다. 왜냐하면 개발자가 그곳에서 활동적으로 활동하고 있기 때문입니다. 이것은 OP가 실사를 수행했고 이미 커밋 로그 (VonC가 아래 인용 함)를보고 원래 개발자가 제공 할 수있는 더 많은 컨텍스트를 원한다고 가정합니다. – JimB

답변

4

표현 "컨텍스트 등록"처음 런타임 코드 생성을 방지뿐만 아니라

하는 Go 1.1 Function Calls

변화의 reflect.MakeFunc 구현을 3 단계를 구현하기위한 (1.1rc2 이동 2 월 2013) commit b1b67a3 등장

그것은 2 월 2014 년 commit 4a000b9에서 주웠다

가, 조립 및 시스템, 1.3beta1 이동 어디 sigreturn is managed as 네이티브 클라이언트 x86-64에 대한 호출

NaCl은 전통적인 운영 체제 책임을 철저히 이행했으며 'sigreturn'을 구현하는 것을 거부했습니다.
대신 우리 프로그램의 실행으로 돌아갈 수있는 유일한 방법은 레지스터를 스스로 복원하는 것입니다. 하나

  • (1) 레지스터로 점프하는 경우없이 순서를 종료 PC의 최종 업데이 트를 할 수있는 방법이 없기 때문에

    불행하게도, 즉, 엄격한 충실 할 불가능하다 레지스터는 의도 한 값 대신에 PC 값을 유지하거나, PC을 스택에 저장하고 SP이 유효하며 그 아래에있는 단어를 깨뜨릴 수있는 조건을 부과하는 RET을 사용하여

  • (2)를 종료합니다.

두 번째는 일반적으로 염화나트륨에 대한 것을 제외하고, 링커는 "POP reg; AND $~31, reg; JMP reg"에 RET를 다시 작성해야, 두 악마의 낮은 것, 그래서 어느 쪽이든 우리는 입력 신호의 결과로 레지스터를 잃어 가고있다 .

마찬가지로, EFLAGS을 복원 할 방법이 없습니다. 일반적인 방법은 POPFL을 사용하는 것이지만 NaCl은 해당 명령을 거부합니다.
비트를 검사하고 플래그 설정을 다시 만들도록 설계된 일련의 명령을 실행할 수는 있지만 많은 작업이 필요합니다.

고맙게도 Go의 신호 처리기는 실행 코드로 직접 복귀하지 않으므로 모든 레지스터와 EFLAGS은 죽어 버릴 수 있습니다.
중요한 레지스터는 신호 처리기가 만든 시뮬레이션 된 호출에 대해 설정하는 레지스터뿐입니다.
오늘은 그 레지스터 그냥 PCSP하지만, 경우에 추가 레지스터는 미래에 관련된 우리는 가능한 한 많은 레지스터를 복원 (예를 DX의 이동 FUNC context register입니다).

Go1의 경우 최근 (Q4 2016).8, 우리는 eliminating stack rescanning를 들어, commit d5bd797commit bf9c71c 있습니다

morestackgobuf.ctxt에 컨텍스트 포인터를 기록하지만 morestack이 어셈블리로 작성되어 있기 때문에 (그리고이 상태 매우 조심해야), 그것은하지 하지 이 쓰기에 필요한 쓰기 장벽을 호출하십시오. 대신 나중에 newstack에이 패치를 적용하여 을 ctxt에 대한 명시적인 쓰기 장벽을 호출합니다.

이것은 이미 약간의 추론을 필요로하며, 하이브리드 장벽으로 털이 많아 질 것입니다.

전체 메커니즘을 단순화하여이 문제를 해결하십시오. morestack에 대신 쓰기 gobuf.ctxt
, newstack에 상황에 맞는 레지스터의 값을 전달하고 gobuf.ctxt에 기록 할 수 있습니다. 이것은 일반 Go 포인터 쓰기이므로 일반 Go 쓰기 장벽을 가져옵니다. 미묘한 추론은 필요하지 않습니다.

관련 문제