음.. V8에 대해서 조사를 했을 때, 너무 예전 것을 공부해서 터보 팬 관련해서 새롭게 알아보기 위해 살펴보니 해당 글을 보는게 유용할 것 같다고 해서 알아보려고 한다. 2013년에 쓰여진 글이지만 터보팬을 이해하는데 도움이 된다니까 알아보자.
대부분의 개발자들은 JIT 컴파일러에 대해 들어본 적이 있으며, 이 JIT 컴파일러가 인터프리터 방식으로 동작하는 언어를 네이티브 코드와 유사한 속도로 실행할 수 있게 해준다는 것을 알고 있다. 그러나 이 JIT가 정확히 어떻게 작동하는지 이해하는 사람은 많지 않으며 자체 컴파일러를 작성할 수 있는 사람은 더 적다.
적어도 컴파일러 내부에 대한 기본 지식이 있으면 해당 소프트웨어에서 실행되는 코드에 대한 이해가 크게 향상될 수 있다.
이 문서에서는 JIT 컴파일에 대한 몇 가지 핵심 개념을 살펴보고, 직접 컴파일러를 구현해볼 것이다!
약간의 컴파일러 기본 지식을 알고 있다면, 모든 컴파일러가 입력을 어떤 형식(일반적으로 소스 코드)에서 다른 형식(일반적으로 기계 코드)으로 변환하는 것으로 가정할 수 있다. JIT 컴파일러도 예외는 아니다.
그것들을 정말로 특별하게 만드는 것은 그것들이 (gcc, clang 등과 같은) 미리 실행되는 것이 아니라 Just-In-Time(즉, 컴파일러의 출력을 실행하기 직전)에 실행된다는 사실이다.
자체 JIT 컴파일러 개발을 시작하려면 입력 언어를 선택해야 한다. 2013년 TOP GITHUB LANGUAGES FOR 2013(SO FAR)을 고려할 때 JavaScript는 단순화된 의미 체계로 일부 제한된 하위 집합을 구현하기에 좋은 후보인 것 같다. 우리는 JavaScript 자체에서 JIT 컴파일러를 구현할 것이다. 이것을 META-META라고 부를 수 있다!
우리의 컴파일러는 JavaScript 소스 코드를 입력으로 받아들이고 매우 인기 있는 X64 플랫폼용 기계 코드를 생성(및 즉시 실행)한다. 그러나 사람이 텍스트 표현으로 작업하는 것이 꽤 편하지만 컴파일러 개발자는 일반적으로 최종 기계 코드를 생성하기 전에 여러 중간 표현(IR)을 만드는 경향이 있다.
단순화된 컴파일러를 작성하고 있으므로 하나의 IR만 있으면 충분하며 이 목적을 위해 AST(Abstract Syntax Tree) 표현을 선택한다.
요즘에는 JavaScript 코드에서 AST(Abstract Syntax Tree)를 가져오는 것이 정말 쉽다. 수십 가지의 라이브러리 중에서 원하는 라이브러리를 선택할 수 있다. 예를 들어, esprima, uglify-js 등이 있다. 함께 일관된 방식으로 작업하기 위해 esprima를 선택하는 것을 추천한다. 이 라이브러리는 멋지고 잘 정의된 출력 형식을 가지고 있다.
예를 들어, 이 코드는 obj.method(42)
다음 AST를 생성합니다( 사용 esprima.parse("...")
).
{
type: 'Program';
body: [
{
type: 'ExpressionStatement',
expression: {
type: 'CallExpression',
callee: {
type: 'MemberExpression',
computed: false,
object: { type: 'Identifier', name: 'obj' },
property: { type: 'Identifier', name: 'method' }
},
arguments: [
{ type: 'Literal', value: 42 }
]
}
}
]
}
요약하자면: JavaScript 소스( check ), AST( check )가 있고 이에 대한 기계 코드를 얻고 싶다.
이미 어셈블리 언어에 익숙하다면 이 장을 건너뛸 수 있다. 이 장에는 이 주제에 대한 기본 소개 자료만 포함되어 있다. 그러나 처음 접하는 경우 먼저 몇 가지 기본 사항을 배우지 않고 다음 장을 읽는 것이 어려울 수 있다.