⚙️ 1. TurboFan의 특정 최적화 전략
TurboFan은 바이트코드 → 머신코드로 변환하면서 다양한 Speculative Optimization (가정 기반 최적화)을 수행해.
주요 전략:
🔹 타입 추론(Type Feedback 기반)
- 실행 중 수집한 Inline Cache(IC) 정보를 바탕으로 변수 타입을 예측
- 예: x + y → x, y가 항상 number였으면 float64 연산 코드 생성
🔹 Escape Analysis
- 객체가 함수 바깥에서 참조되지 않으면 힙 대신 스택에 할당 → GC 부담 감소
🔹 Loop Peeling / Unrolling
- 루프 첫 바퀴 따로 빼거나 반복 루프를 미리 펼쳐서 분기 수 줄이기
🔹 Dead Code Elimination (DCE)
- 사용되지 않는 코드 삭제
- if (false) {...} → 통째로 제거
🔹 Strength Reduction
- 느린 연산을 더 빠른 연산으로 교체
- 예: x * 2 → x << 1
🔹 Control Flow Simplification
- 여러 분기(branch)를 병합하거나 단순화
- 예: if-else가 항상 특정 방향으로만 흐르면 반대 분기 제거
🧩 2. V8 내부 C++ 구조
- V8은 완전히 C++로 구성되어 있고, 주요 모듈은 아래처럼 구성돼 있어:
🧱 주요 컴포넌트
컴포넌트 | 설명 |
---|
src/objects/ | JS 객체와 관련된 구조체들 (JSObject, JSFunction 등) |
src/compiler/ | TurboFan 전체 (graph builder, optimizer, lowering, codegen) |
src/interpreter/ | Ignition 바이트코드 인터프리터 |
src/runtime/ | JS 내장 함수 구현 (예: Math, Array 내부 동작) |
src/heap/ | 메모리 및 GC 관련 코드 |
src/codegen/ | 머신 코드 생성기 (플랫폼별 코드 포함) |
🔧 핵심 클래스 예시
- Handle: GC에 안전한 스마트 포인터
- Zone: 임시 객체를 위한 영역 메모리 할당기
- Node: TurboFan의 노드 기반 IR
- JSFunction: JS 함수 객체 클래스
🧨 3. Deoptimization 사례 분석
V8은 Speculative Optimization 기반으로 동작하므로, 잘못된 가정이 깨질 때 Deopt가 발생함.
function add(x, y) {
return x + y;
}
add(1, 2);
add("a", "b");
🔍 발생 시점
- +연산자는 처음엔 수치 연산으로 최적화됨 (number + number)
- 문자열이 들어오면 타입 가정 깨짐 → 기존 컴파일 코드 버리고 fallback
🔄 처리 과정
- Deopt trigger → bailout point로 점프
- 원래 바이트코드 상태 복원
- 바이트코드 인터프리터로 실행 재시작
- 최적화 다시 시도 가능 (다시 feedback 수집)
🔧 관련 디버깅 플래그
--trace-deopt
--trace-opt
--print-opt-code
⚡️ 4. Inline Cache(IC) 작동 시퀀스
Inline Cache는 객체 프로퍼티 접근 성능을 높이기 위한 핵심 구조야.
function getName(obj) {
return obj.name;
}
🧠 작동 흐름
1️⃣ 1차 실행
- obj.name 접근 시 객체 구조(Shape/Map) 기록
- IC 상태: Uninitialized → Monomorphic
2️⃣ 동일 구조 반복
- 동일 구조 객체 계속 접근하면 바로 address lookup 가능
- IC는 구조 → offset 캐싱해서 바로 obj + offset 로 접근
3️⃣ 다른 구조 등장
- obj2.name인데 구조 다르면 → IC가 Polymorphic 또는 Megamorphic 상태로 진화
- Megamorphic 되면 일반적인 dictionary lookup으로 fallback
💡 실제 성능 팁
프로퍼티 순서 바꾸거나 다르게 정의하면 Hidden Class 다르게 생성됨 → IC 깨짐 → Deopt 유발 가능