스택리스 언어는 어떻게 작동합니까?
스택리스 언어에 대해 들어 봤습니다. 그러나 나는 언어가 어떻게 구현 될지 전혀 모른다. 누군가 설명 할 수 있습니까?
우리가 가지고있는 최신 운영합니다 (Windows, Linux)는 내가 "빅 스택 모델"이라고는 방식으로 작동합니다. 그리고 그 모델은 틀 렸으며 "스택없는"언어에 대한 응답을 유발합니다.
"빅 스택 모델"은 된 프로그램이 메모리의 연속 영역에서 함수 호출을 위해 "스택 프레임"을 할당 가정합니다. 기계 경도를 사용하여 스택 포인터 (및 연설 스택 프레임 포인터)를 포함하는 많은 것을 매우 빠르게 조정합니다. 빠른 함수 호출을 수행하고 있습니다. 최신 OS에서 실행되는 모든 프로그램의 99.99 %가 빅 스택 모델에서 잘 작동하기 때문에 컴파일러, 로더, 심지어 OS 도이 스택 영역에 대해 "알고"있습니다.
모든 애플리케이션의 공통적 인 문제 중 하나는 "내 스택이 얼마나 커야입니까?"입니다. . 메모리가 성능하기 때문에 대부분의 경우 스택을 위해 큰 청크가 따로 설정되고 (MS 다중은 1Mb) 일반적인 응용 프로그램 호출 구조는 사용하지 않습니다. 그러나 응용 프로그램이 스택에 다 사용하면 모든 것에 접근하기 때문에 잘못된 메모리 참조 ( "Dave 미안합니다. 할 수 없습니다")와 함께 죽습니다.
대부분의 소위 "스택리스"언어는 실제로 스택리스가 아닙니다. 그들은 사용하지 않는 연속 스택을 제공합니다. 대신 그들이하는 일은 각 호출 함수에서 힙에서 스택 프레임을 할당하는 것입니다. 함수 호출 당 비용은 다소 증가합니다. 함수가 일반적으로 복잡하거나 언어가 해석 적이라면 추가 비용은 미미합니다. (또한 프로그램 호출 그래프에서 호출 DAG를 확인하고 전체 DAG를 포괄하는 힙 세그먼트를 할당 할 수 있습니다. 이렇게하면 DAG 내부의 호출에 대해 힙 할당과 고전적인 빅 스택 함수 호출 속도를 모두 얻을 수 있습니다) .
스택 프레임에 힙 할당을 사용하는 데는 몇 가지 이유가 있습니다.
1) 프로그램이 해결중인 미리 특정 문제에 따라 심층 재귀를 수행하는 경우 필요한 크기를 알 수 없기 때문에 "큰 스택"영역을 할당하기 매우 어렵습니다. 스택이 충분한 지 확인하기 위해 어색하게 함수 호출을 정렬 할 수 있고, 할당 된 경우 더 큰 청크를 재 할당하고 이전 스택을 복사하고 모든 포인터를 스택에 다시 배치 할 수 있습니다. 너무 어색해서 어떤 구현도 알지 못합니다. 스택 프레임을 할당한다는 것은 말 그대로 할당 가능한 메모리가 남아 있지 않을 때까지 애플리케이션이 미안할 것이 없음을 의미합니다.
2) 프로그램은 하위 작업을 포크합니다. 각 하위 작업에는 자체 스택이 필요하며 하나의 "큰 스택"을 사용할 수 없습니다. 따라서 각 하위 작업에 스택을 할당해야합니다. 수천 개의 가능한 하위 작업이있는 경우 이제 수천 개의 "큰 스택"이 필요할 때 갑자기 터무니없는 메모리 요구가 발생합니다. 스택 프레임을 할당하면이 문제가 해결됩니다. 종종 하위 작업 "스택"은 어휘 범위 지정을 구현하기 위해 상위 상위 작업을 다시 참조합니다. 하위 작업 분기로 "선인장 스택"이라는 "하위 스택"트리가 생성됩니다.
3) 귀하의 언어는 계속됩니다. 이를 위해 현재 함수에서 볼 수있는 어휘 범위의 데이터를 나중에 다시 사용할 수 있도록 보존해야합니다. 이 부모 스택 프레임을 복사하고 선인장 스택을 올라간 다음 계속해서 구현할 수 있습니다.
PARLANSE의 I 구현 프로그래밍 언어 1)과 2)를 수행합니다. 나는 3)에서 일하고 있습니다.
Stackless Python은 여전히 Python 스택이 프리터 (꼬리 호출 최적화 및 기타 호출 프레임 병합 트릭이있을 수 있음) 인터의 C 스택과 완전히 분리되어 있습니다.
Haskell (일반적으로 구현 됨)에는 호출 스택이 없습니다. 평가는 그래프 축소를 기반으로 합니다 .
http://www.linux-mag.com/cache/7373/1.html에 언어 프레임 워크 Parrot에 대한 멋진 가이드가 있습니다 . Parrot은 호출에 스택을 사용하지 않습니다 설명이 기사에서는 약간의 기술에 대해 설명합니다.
이없는 환경에서는 (튜링 머신, 어셈블리 및 Brainfuck)에 어느 정도 익숙한 자체 스택을 구현하는 것이 일반적입니다. 언어에 스택을 설치하는 것은 없습니다.
가장 실용적인 어셈블리에서는 사용 가능한 메모리 영역을 선택하고 스택에서 맨 아래를 가리 키도록 설정 한 다음 푸시 및 팝을 구현하기 위해 증가 또는 감소합니다.
편집 : 일부 아키텍처에는 전용 스택이 준비 할 필요가 없습니다.
이 기사에는 이해하기 쉬운 설명이 있습니다. http://www.defmacro.org/ramblings/fp.html
연속은 스택 언어의 함수에 사용하여 "스택없는"상태로 만들 수도 있습니다. 물론 스택은 여전히 존재하지만 Ira Baxter가 설명했듯이 하나의 큰 연속 세그먼트가 아닙니다.
스택리스 C를 구현하고 싶다고 가정 해 보겠습니다. 가장 먼저 깨달아야 할 스택이 필요합니다.
a == b
하지만, 그렇 그렇습니까?
isequal(a, b) { return a == b; }
아니요. 스마트 컴파일러는에 대한 호출을 인라인 isequal
하여 a == b
. 모든 것을 인라인하지 않는 이유는 무엇입니까? 물론 더 많은 코드를 생성 할 수 있고 스택을 제거하는 것이 가치가있는 약간의 절충으로 쉽게 수행 할 수 있습니다.
재귀는 어떻습니까? 문제 없어요. 다음과 같은 꼬리 재귀 함수 :
bang(x) { return x == 1 ? 1 : x * bang(x-1); }
실제로는 루프이기 때문에 위장은 여전히 인라인이 될 수 있습니다.
bang(x) {
for(int i = x; i >=1; i--) x *= x-1;
return x;
}
이론적으로는 정말 똑똑한 컴파일러가 당신을 위해 그것을 알아낼 수 있습니다. 그러나 덜 똑똑한 사람은 여전히 그것을 고토로 평평하게 만들 수 있습니다.
ax = x;
NOTDONE:
if(ax > 1) {
x = x*(--ax);
goto NOTDONE;
}
작은 트레이드 오프를해야하는 경우에 있습니다. 인라인 할 수 없습니다.
fib(n) { return n <= 2 ? n : fib(n-1) + fib(n-2); }
스택리스 C는 제출할 수 없습니다. 많이 포기하고 있습니까? 별로. 이것은 아니 C도 잘 할 수없는 일입니다. 나를 믿지 얼마나 그냥 전화 fib(1000)
해서 당신의 소중한 컴퓨터에 무슨 일이 일어나는지보세요.
나를 고대라고 부르지 만 FORTRAN 표준과 COBOL이 재귀 호출을 지원하지 않아 스택이 필요하지 갑자기 던 때를 기억할 수 있습니다. 스택이없는 CDC 6000 시리즈 머신의 구현을 기억하고 실행할 것, FORTRAN은 서브 루틴을 재귀하여 호출하려고하면 이상한 일을 할 것입니다.
레코드를 위해 호출 스택 대신 CDC 6000 시리즈 명령어 세트는 RJ 명령어를 사용하여 서브 루틴을 호출했습니다. 이렇게하면 통화 대상 위치에 현재 PC 값이 저장되고 다음 위치로 분기됩니다. 마지막에 서브 루틴은 호출 대상 위치로 간접 점프를 수행합니다. 그로 인해 저장된 PC가 다시로드되어 효과적으로 발신자에게 돌아 왔습니다.
분명히 재귀 호출에서는 작동하지 않습니다. (그리고 내 기억은 재귀를 시도하면 CDC FORTRAN IV 컴파일러가 손상된 코드를 생성한다는 것입니다 ...)
내가 틀렸다면 자유롭게 수정하십시오.하지만 각 함수 호출 프레임에 대해 힙에 메모리를 할당하면 과도한 메모리 스 래싱이 발생할 것이라고 생각합니다. 결국 운영 체제는이 메모리를 관리해야합니다. 이 메모리 스 래싱을 피하는 방법은 호출 프레임을위한 캐시라고 생각합니다. 어쨌든 캐시가 필요하다면 메모리에서 연속적으로 만들고 스택이라고 부를 수도 있습니다.
참조 URL : https://stackoverflow.com/questions/1016218/how-does-a-stackless-language-work
'ProgramingTip' 카테고리의 다른 글
kotlin.jvm.KotlinReflectionNotSupportedError : 실행시 Kotlin 리플렉션 구현을 사용할 수 없습니다. (0) | 2020.12.15 |
---|---|
Django 기반 프로젝트의 A / B 테스트에 대한 의견이 있으십니까? (0) | 2020.12.15 |
웹에 저장 색상이 여전히 관련이 있습니까? (0) | 2020.12.15 |
New Intent ()는 Android에서 새 인스턴스를 시작합니다. launchMode =“singleTop” (0) | 2020.12.15 |
특정 시간의 시간 가져 오기 (0) | 2020.12.15 |