다음의 데이터는 각각 분리된 공간에 저장
- 다양한 사용 패턴에 대한 속성/요소 효율적 추가/액세스 가능
- Elements:
[1, 2, 3]
- 정수형 인덱스로 위치 파악 가능
- 메모리 절약 위해 sparse dictionary 사용 가능
- Array-indexed properties: elements store에 저장
- Properties:
[a: 'hello', b: 'world']
- 키로 위치 파악 어려움
- HiddenClass 사용
- Named properties: properties store에 저장
- Elements와 properties는 각각 배열이나 딕셔너리(해쉬 테이블)에 저장될 수 있음
Hidden Class
- 객체의 구조와 속성의 메타 데이터를 저장하는 구조
V8 엔진에서 객체의 첫 번째 필드는 히든 클래스를 가리키는 포인터
- 히든 클래스에 포함되는 정보
- 프로퍼티 개수 (세 번째 필드)
- 프로토타입 참조
- Descriptor Array 포인터
- Descripitor Array는 프로퍼티 이름과 위치 저장
- length
- EnumCache
- key
- details (enumerable, configurable, writeable)
- 동일한 구조를 가진 객체는 동일한 히든 클래스 공유
- 새로운 속성이 추가 시 히든 클래스 변경
- 기존 히든 클래스는 보존되어 transition tree 형성
- 같은 transition tree 내의 히든 클래스는 Descriptor Array 공유
- Transition Array에는 형제 히든 클래스로 분기하기 위한 property name을 저장
Named Properties
In-object properties
- 객체 내에 저장되는 프로퍼티
- 개수는 초기 크기에 의해 결정
- 객체의 공간을 초과하는 추가 속성은 properties store에 저장
Fast Properties
- 선형 시간에 접근 가능한 경우 일반적으로 빠르다고 판단
- properteis store 내의 Fast properties는 인덱스로 접근 가능
- 히든 클래스의 descriptor array를 참조하여 실제 위치에 접근
Slow Properties
- 객체에 많은 속성이 추가되거나 삭제되면 히든 클래스 및 descriptor array의 유지에 오버헤드가 발생
- 이런 경우에는 딕셔너리가 사용
- 메타데이터는 descriptor array가 아니라 직접 딕셔너리에 저장
- 각 항목은 key, value, details로 구성
- details (enumerable, configurable, writeable)
인라인 캐시?
Elements, Array-indexed Properties
Packed & Holey Elements
- 배열에서 중간 원소를 삭제하거나 정의하지 않은 경우 빈 공간 존재
- 비어 있는 element가 있으면 프로토타입 체인을 확인하여 속성 검색
_hole
값은 존재하지 않는 속성을 표시하는 특별한 값
- _hole
값이 없는 경우 배열은 packed된 상태
- 프로토타입 체인을 확인할 필요 없음
Fast & Dictionary Elements
- Fast elements: 요소 인덱스가 elements store의 인덱스와 직접 매핑되어 빠른 접근 속도를 제공
- Dictionary elements: 메모리를 절약하기 위해 사용되는 방식이며, 큰 희소 배열이나 구멍이 많은 배열에 적합
- 키 - 값 - 디스크립터 저장
- 사용자 정의 설명자를 정의할 때 히든 클래스에 설명자 세부 정보를 저장할 수 없어 dictionary(slow) elements를 사용
ElementAccessor
- 20가지의 요소 유형에 대해 Array 함수를 개별적으로 작성하는 것을 방지
- Array 함수 호출 시 ElementAccessor를 통해 특정 유형에 맞는 함수 버전으로 디스패치
- backing store에서 elements에 접근하는 간단한 함수만 구현
typed array, string wrapper에 해당하는 배열은 어떻게?
hidden class에 덧 붙이는 내용
- JavaScript에서 class는 syntax sugar
- Hidden class는 어떻게 구현되고 동작할까
function Peak(name, height, extra) {
this.name = name;
this.height = height;
if (isNaN(extra)) {
this.experience = extra;
} else {
this.prominence = extra;
}
}
m1 = new Peak("Matterhorn", 4478, 1040);
m2 = new Peak("Wendelstein", 1838, "good");
이 때 히든 클래스의 transition은
1. 프로퍼티가 없는 hidden class
2. name
3. name, height
4. name, heigt, promonence / name, height, experience
이 상태에서 7개의 peak 객체를 만들면 3개의 in-object property가 있고 추가적인 프로퍼티는 in-object로 둘 수 없다. 객체의 프로퍼티 backing store에 저장될텐데 이건 위에서 본 프로퍼티 value들의 배열이다. 인덱스는 앞서 봤듯 Descriptor Array에서 가져온다.
이 때 m2 변수에 프로퍼티를 추가를 한 뒤 V8의 관점에서 hidden class들을 보면 프로퍼티들은 모두 const로 보일 텐데 이는 생성자 이후로 아무것도 변경되지 않았기 때문이다.
TurboFan은 이런 상황을 좋아한다.
어떤 함수가 m2를 constant global로 참조한다면 m2.cost 는 컴파일 타임에 알 수 있다.
cost는 backing stroe에 저장되어 있을 것이다. (0번 인덱스에)
`%DebugPrint(m2)
:`