# **Quá trình compile Javascript của V8**

- **Parsing** : Phân tích cú pháp mã nguồn để chuyển đổi thành *Abstract Syntax Tree (AST)*
- **Ignition** : V8 sử dụng *Ignition* tạo bytecode từ AST
- **Optimising Compiler** : V8 sử dụng trình biên dịch ***TurboFan*** để biên dịch sang mã máy, **TurboFan** sử dụng nhiều kỹ thuật để tạo ra mã máy tối ưu nhất có thể
- Cuối cùng là giai đoạn thực thi
> V8 sử dụng ***Just-in-Time compilation (JIT)*** để biên dịch mã nguồn hoặc mã bytecode thành mã máy trực tiếp trong quá trình chạy của một chương trình, để cải thiện hiệu xuất và giảm thời gian thực thi
# **Build bản debug của V8**
- Ở task 1 ta đã build phiên bản ```release```, để debug với V8 ta sẽ build V8 với phiên bản ```debug``` sẽ hỗ trợ trong quá trình debug
- Để build phiên bản ```debug``` ta cài đặt cấu hình GN và build
```
tools/dev/v8gen.py x64.debug
ninja -C out.gn/x64.debug
```
- Tạo mục ```~/.gdbinit``` để thêm extension ```gdbinit``` và ```gdb-v8-support.py``` từ mục tools vào
```
source ~/v8/tools/gdbinit
source ~/v8/tools/gdb-v8-support.py
```
> Hoặc có thể trong ```gdb``` mình dùng trực tiếp 2 câu lệnh trên để thêm extension
# **Memory structure**
### **Small Integer**
- số nguyên nhỏ trong Javascript được ghi rõ nên không cần cấp phát bộ nhớ nên khi debug không có thông tin về memory của biến
```javascript
d8> let a = 10
undefined
d8> %DebugPrint(a)
DebugPrint: Smi: 0xa (10)
10
```
- Thử lấy một số nguyên lớn
```java
d8> %DebugPrint(2**31)
DebugPrint: 0x37ee0029a245: [HeapNumber] in OldSpace
- map: 0x37ee00000809 <Map[12](HEAP_NUMBER_TYPE)>
- value: 2147483648.0
0x37ee00000809: [Map] in ReadOnlySpace
- map: 0x37ee000004cd <MetaMap (0x37ee00000085 <null>)>
- type: HEAP_NUMBER_TYPE
- instance size: 12
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x37ee00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x37ee00000759 <DescriptorArray[0]>
- prototype: 0x37ee00000085 <null>
- constructor: 0x37ee00000085 <null>
- dependent code: 0x37ee00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
2147483648
```
- Số nguyên lớn thuộc kiểu ```HeapNumber``` vì số lớn hơn số biểu diễn của 31 bit nên sẽ được biểu diễn dạng số thực
### **Double value**:
- giá trị số thực được cấp phát bộ nhớ và nằm ở ```0x2c3a00299b15```, thuộc kiểu ```HeapNumber``` nằm ở ```Oldspace```
> - ```Oldspace``` là vùng bộ nhớ ở heap để lưu trữ các dữ liệu đã tồn tại lâu và không được giải phóng
> - ```HeapNumber``` là đối tượng để biểu diễn số thực
```java
d8> a = 3.14
3.14
d8> %DebugPrint(a)
DebugPrint: 0xcbb00299d09: [HeapNumber] in OldSpace
- map: 0x0cbb00000809 <Map[12](HEAP_NUMBER_TYPE)>
- value: 3.14
0xcbb00000809: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: HEAP_NUMBER_TYPE
- instance size: 12
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
3.14
```
```bash
pwndbg> x/10gx 0xcbb00299d09-5
0xcbb00299d04: 0x0000080900000010 0x40091eb851eb851f
0xcbb00299d14: 0x004018000000117d 0x0000000000000000
0xcbb00299d24: 0x00000002000008d1 0x0000000100000000
0xcbb00299d34: 0x0000072500281e91 0x0020a60100000725
0xcbb00299d44: 0x0028172900299cb9 0x0000074100299d55
```
- Vì là số thực nên khi biểu diễn trên máy tính sẽ chuyển đổi theo chuẩn ```IEEE 754```, ```3.14``` sẽ được biểu diễn là ```0x40091eb851eb851f```
### **String** :
- địa chỉ của string là ```0xcbb00298d99``` và cũng được lưu trữ ở ```Oldspace``` và có kích thước không xác định vì chuỗi có thể thay đổi
```java
d8> a = "Hello World"
"Hello World"
d8> %DebugPrint(a)
DebugPrint: 0xcbb00298d99: [String] in OldSpace: #Hello World
0xcbb000003dd: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: INTERNALIZED_ONE_BYTE_STRING_TYPE
- instance size: variable
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- non-extensible
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
"Hello World"
```
- Ta dùng gdb để xem chuỗi đang lưu trữ trong bộ nhớ
```bash
pwndbg> x/10gx 0xcbb00298d99
0xcbb00298d99: 0x0be901b432000003 0x6f6c6c6548000000
0xcbb00298da9: 0xe500646c726f5720 0xbf00000002000005
0xcbb00298db9: 0x0000000d3900298d 0xedfffffffe004000
0xcbb00298dc9: 0x5100298e1d00298d 0x000001000000298d
0xcbb00298dd9: 0x0008001000000200 0x000000032a000000
pwndbg> x/s 0xcbb00298d99+0xb
0xcbb00298da4: "Hello World"
```
### **Array** :
- Địa chỉ của array là ```0x37ee0004a8d9```, ```lenght``` cho biết độ dài array là 3, phần ```elements``` cho biết các phần tử được lưu trữ ở đâu, phần tử 0 và 1 là một smi nên được lưu trữ trực tiếp còn phần tử thứ 2 là một chuỗi nên cần một bộ nhớ để lưu trữ
```java
d8> a = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
d8> %DebugPrint(a)
DebugPrint: 0xcbb0004a8f1: [JSArray]
- map: 0x0cbb0028c629 <Map[16](PACKED_SMI_ELEMENTS)> [FastProperties]
- prototype: 0x0cbb0028c89d <JSArray[0]>
- elements: 0x0cbb00299e8d <FixedArray[5]> [PACKED_SMI_ELEMENTS (COW)]
- length: 5
- properties: 0x0cbb00000725 <FixedArray[0]>
- All own properties (excluding elements): {
0xcbb00000d99: [String] in ReadOnlySpace: #length: 0x0cbb00270811 <AccessorInfo name= 0x0cbb00000d99 <String[6]: #length>, data= 0x0cbb00000069 <undefined>> (const accessor descriptor), location: descriptor
}
- elements: 0x0cbb00299e8d <FixedArray[5]> {
0: 1
1: 2
2: 3
3: 4
4: 5
}
0xcbb0028c629: [Map] in OldSpace
- map: 0x0cbb002816d9 <MetaMap (0x0cbb00281729 <NativeContext[291]>)>
- type: JS_ARRAY_TYPE
- instance size: 16
- inobject properties: 0
- unused property fields: 0
- elements kind: PACKED_SMI_ELEMENTS
- enum length: invalid
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0x0cbb00000a89 <Cell value= 1>
- instance descriptors #1: 0x0cbb0028ceb5 <DescriptorArray[1]>
- transitions #1: 0x0cbb0028ced1 <TransitionArray[4]>Transition array #1:
0x0cbb00000e5d <Symbol: (elements_transition_symbol)>: (transition to HOLEY_SMI_ELEMENTS) -> 0x0cbb0028cee9 <Map[16](HOLEY_SMI_ELEMENTS)>
- prototype: 0x0cbb0028c89d <JSArray[0]>
- constructor: 0x0cbb0028c595 <JSFunction Array (sfi = 0xcbb00275b81)>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
[1, 2, 3, 4, 5]
```
```bash
pwndbg> x/20gx 0x0cbb00299e8d-5
0xcbb00299e88: 0x0000065d00000026 0x000000020000000a
0xcbb00299e98: 0x0000000600000004 0x0000000a00000008
0xcbb00299ea8: 0x00000000000010b5 0x0000117d00299e8d
0xcbb00299eb8: 0x0000000000401a00 0x000008d100000000
0xcbb00299ec8: 0x0000000000000003 0x00281e9100000033
0xcbb00299ed8: 0x0000072500000725 0x00299e3d0020a601
0xcbb00299ee8: 0x00299ef500281729 0x00000b3100000741
0xcbb00299ef8: 0x00000062000020cd 0x0000072500281e91
0xcbb00299f08: 0x0020a60100000725 0x00281729002999e1
0xcbb00299f18: 0x0000074100299f21 0x000020cd00000b31
```
- V8 sử dụng kĩ thuật ```pointer tagging``` nghĩa là sẽ lấy bit có trọng số nhỏ nhất của Smi để đánh dấu còn 31bit còn lại để biểu diễn giá trị, còn con trỏ heap sẽ lấy bit có trọng số thứ 2 để đánh dấu con trỏ mạnh hay yếu
- Trong array này chứa Smi nên các giá trị của nó sẽ bị dịch sang trái 1 bit có nghĩa là giá trị sẽ nhân 2,
### **Arraybuffer**:
```java
d8> a = new ArrayBuffer(16)
[object ArrayBuffer]
d8> %DebugPrint(a)
DebugPrint: 0xcbb0004b8d1: [JSArrayBuffer]
- map: 0x0cbb00289f39 <Map[68](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x0cbb0028a00d <Object map = 0xcbb00297809>
- elements: 0x0cbb00000725 <FixedArray[0]> [HOLEY_ELEMENTS]
- embedder fields: 2
- cpp_heap_wrappable: 0
- backing_store: 0xcbc00000000
- byte_length: 16
- max_byte_length: 16
- detach key: 0x0cbb00000069 <undefined>
- detachable
- properties: 0x0cbb00000725 <FixedArray[0]>
- All own properties (excluding elements): {}
- embedder fields = {
0, aligned pointer: (nil)
0, aligned pointer: (nil)
}
0xcbb00289f39: [Map] in OldSpace
- map: 0x0cbb002816d9 <MetaMap (0x0cbb00281729 <NativeContext[291]>)>
- type: JS_ARRAY_BUFFER_TYPE
- instance size: 68
- inobject properties: 0
- unused property fields: 0
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0x0cbb00000a89 <Cell value= 1>
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb0028a00d <Object map = 0xcbb00297809>
- constructor: 0x0cbb00289ee9 <JSFunction ArrayBuffer (sfi = 0xcbb0027a081)>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
[object ArrayBuffer]
```
- ```backing_store: 0xcbc00000000``` là địa chỉ thực để lưu dữ liệu đầu tiên
```bash
pwndbg> x/20gx 0xcbc00000000
0xcbc00000000: 0x0000000000000000 0x0000000000000000
0xcbc00000010: 0x0000000000000000 0x0000000000000000
0xcbc00000020: 0x0000000000000000 0x0000000000000000
0xcbc00000030: 0x0000000000000000 0x0000000000000000
0xcbc00000040: 0x0000000000000000 0x0000000000000000
0xcbc00000050: 0x0000000000000000 0x0000000000000000
0xcbc00000060: 0x0000000000000000 0x0000000000000000
0xcbc00000070: 0x0000000000000000 0x0000000000000000
0xcbc00000080: 0x0000000000000000 0x0000000000000000
0xcbc00000090: 0x0000000000000000 0x0000000000000000
```
### **Pointer**:
- V8 sử dụng ```Pointer Compression``` để đưa con trỏ về 32 bit với bit có trọng số nhỏ nhất là 1, nên khi cần địa chỉ thực ta cần trừ đi 1 và cộng với địa chỉ base
### **Special value**:
#### undefined:
```javascript
d8> var e
undefined
d8> %DebugPrint(e)
DebugPrint: 0xcbb00000069: [Oddball] in ReadOnlySpace: #undefined
0xcbb000004f5: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: ODDBALL_TYPE
- instance size: 28
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- undetectable
- non-extensible
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
undefined
```
```bash
pwndbg> x/gx 0xcbb00000069
0xcbb00000069: 0x0000000000000004
```
#### Null
```javascript
d8> a = null
null
d8> %DebugPrint(a)
DebugPrint: 0xcbb00000085: [Oddball] in ReadOnlySpace: #null
0xcbb0000051d: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: ODDBALL_TYPE
- instance size: 28
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- undetectable
- non-extensible
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
null
```
```bash
pwndbg> x/gx 0xcbb00000085
0xcbb00000085: 0x0000000000000005
```
#### True
```javascript
d8> a = true
true
d8> %DebugPrint(a)
DebugPrint: 0xcbb000000c9: [Oddball] in ReadOnlySpace: #true
0xcbb00000545: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: ODDBALL_TYPE
- instance size: 28
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- non-extensible
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
true
```
```
pwndbg> x/gx 0xcbb000000c9
0xcbb000000c9: 0x0000000000000005
```
#### False
```javascript
d8> a = false
false
d8> %DebugPrint(a)
DebugPrint: 0xcbb000000ad: [Oddball] in ReadOnlySpace: #false
0xcbb00000545: [Map] in ReadOnlySpace
- map: 0x0cbb000004cd <MetaMap (0x0cbb00000085 <null>)>
- type: ODDBALL_TYPE
- instance size: 28
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- non-extensible
- back pointer: 0x0cbb00000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x0cbb00000759 <DescriptorArray[0]>
- prototype: 0x0cbb00000085 <null>
- constructor: 0x0cbb00000085 <null>
- dependent code: 0x0cbb00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
false
```
```
pwndbg> x/gx 0xcbb000000ad
0xcbb000000ad: 0x0000000000000005
```
~~Không hiểu tại sao các special value lại có các giá trị này và không hiểu tại sao các địa chỉ thực của data với địa chỉ được in ra ở DebugPrint lại có offset như vậy~~
# **UPDATE**
## Hidden Class
- Khi một object được tạo trong Javascript đều có một ***Hidden Class*** riêng để theo dõi cấu trúc các thuộc tính (property) hiện có và vị trí bộ nhớ của chúng. Khi thêm, xóa hay thay đổi thuộc tính thì một ***Hidden Class*** mới được tạo. ***Hidden Class*** giúp tối ưu hóa thời gian truy cập đến một thuộc tính của object
```javascript=
d8> let object = {a:"hello", b:"world", c:10, d:true}
undefined
d8> %DebugPrint(object)
DebugPrint: 0x290e0004ae6d: [JS_OBJECT_TYPE]
- map: 0x290e0029a0b5 <Map[28](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x290e002825d9 <Object map = 0x290e00281c15>
- elements: 0x290e00000725 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x290e00000725 <FixedArray[0]>
- All own properties (excluding elements): {
0x290e00002b19: [String] in ReadOnlySpace: #a: 0x290e00298db1 <String[5]: #hello> (const data field 0), location: in-object
0x290e00002b29: [String] in ReadOnlySpace: #b: 0x290e00299cd1 <String[5]: #world> (const data field 1), location: in-object
0x290e00002b39: [String] in ReadOnlySpace: #c: 10 (const data field 2), location: in-object
0x290e00002b49: [String] in ReadOnlySpace: #d: 0x290e000000c9 <true> (const data field 3), location: in-object
}
0x290e0029a0b5: [Map] in OldSpace
- map: 0x290e002816d9 <MetaMap (0x290e00281729 <NativeContext[291]>)>
- type: JS_OBJECT_TYPE
- instance size: 28
- inobject properties: 4
- unused property fields: 0
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x290e0029a08d <Map[28](HOLEY_ELEMENTS)>
- prototype_validity cell: 0x290e00000a89 <Cell value= 1>
- instance descriptors (own) #4: 0x290e0004af01 <DescriptorArray[4]>
- prototype: 0x290e002825d9 <Object map = 0x290e00281c15>
- constructor: 0x290e0028211d <JSFunction Object (sfi = 0x290e00275161)>
- dependent code: 0x290e00000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
{a: "hello", b: "world", c: 10, d: true}
```
- Khi một object được tạo ta thấy các trường *map*, *prototype*, *elements*, *properties*
### Prototype
- Là một tham chiếu đến object khác cho phép object đó có tính kế thừa object hiện tại, có nghĩa là mang thuộc tính và phương thức của object hiện tại.
### Elements
- *Elements* là một object, nếu key của thuộc tính thuộc kiểu *Integer* thì sẽ được lưu trữ trong *Elements*, ví dụ trên *Element* không chứa gì vì trong object hiện tại các key không thuộc kiểu *Integer*
- ##### Elements kind
```java=
d8> var a = [1, 2, 3, 4, 5]
undefined
d8> %DebugPrint(a)
DebugPrint: 0x3201000487bd: [JSArray]
- map: 0x32010028c629 <Map[16](PACKED_SMI_ELEMENTS)> [FastProperties]
- prototype: 0x32010028c89d <JSArray[0]>
- elements: 0x320100298e01 <FixedArray[5]> [PACKED_SMI_ELEMENTS (COW)]
- length: 5
- properties: 0x320100000725 <FixedArray[0]>
- All own properties (excluding elements): {
0x320100000d99: [String] in ReadOnlySpace: #length: 0x320100270811 <AccessorInfo name= 0x320100000d99 <String[6]: #length>, data= 0x320100000069 <undefined>> (const accessor descriptor), location: descriptor
}
- elements: 0x320100298e01 <FixedArray[5]> {
0: 1
1: 2
2: 3
3: 4
4: 5
}
0x32010028c629: [Map] in OldSpace
- map: 0x3201002816d9 <MetaMap (0x320100281729 <NativeContext[291]>)>
- type: JS_ARRAY_TYPE
- instance size: 16
- inobject properties: 0
- unused property fields: 0
- elements kind: PACKED_SMI_ELEMENTS
- enum length: invalid
- back pointer: 0x320100000069 <undefined>
- prototype_validity cell: 0x320100000a89 <Cell value= 1>
- instance descriptors #1: 0x32010028ceb5 <DescriptorArray[1]>
- transitions #1: 0x32010028ced1 <TransitionArray[4]>Transition array #1:
0x320100000e5d <Symbol: (elements_transition_symbol)>: (transition to HOLEY_SMI_ELEMENTS) -> 0x32010028cee9 <Map[16](HOLEY_SMI_ELEMENTS)>
- prototype: 0x32010028c89d <JSArray[0]>
- constructor: 0x32010028c595 <JSFunction Array (sfi = 0x320100275b81)>
- dependent code: 0x320100000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
[1, 2, 3, 4, 5]
```
- Vì trong mảng a toàn các smi nên *Elements kind* là ```PACKED_SMI_ELEMENTS``` (ở hàng 26)
- Khi ta thêm vào mảng một giá trị *double*
```java=
d8> a.push(3.4)
6
d8> %DebugPrint(a)
DebugPrint: 0x3201000487bd: [JSArray]
- map: 0x32010028cf29 <Map[16](PACKED_DOUBLE_ELEMENTS)> [FastProperties]
- prototype: 0x32010028c89d <JSArray[0]>
- elements: 0x32010004a6cd <FixedDoubleArray[25]> [PACKED_DOUBLE_ELEMENTS]
- length: 6
- properties: 0x320100000725 <FixedArray[0]>
- All own properties (excluding elements): {
0x320100000d99: [String] in ReadOnlySpace: #length: 0x320100270811 <AccessorInfo name= 0x320100000d99 <String[6]: #length>, data= 0x320100000069 <undefined>> (const accessor descriptor), location: descriptor
}
- elements: 0x32010004a6cd <FixedDoubleArray[25]> {
0: 1
1: 2
2: 3
3: 4
4: 5
5: 3.4
6-24: <the_hole>
}
0x32010028cf29: [Map] in OldSpace
- map: 0x3201002816d9 <MetaMap (0x320100281729 <NativeContext[291]>)>
- type: JS_ARRAY_TYPE
- instance size: 16
- inobject properties: 0
- unused property fields: 0
- elements kind: PACKED_DOUBLE_ELEMENTS
- enum length: invalid
- back pointer: 0x32010028cee9 <Map[16](HOLEY_SMI_ELEMENTS)>
- prototype_validity cell: 0x320100000a89 <Cell value= 1>
- instance descriptors #1: 0x32010028ceb5 <DescriptorArray[1]>
- transitions #1: 0x32010028cf51 <TransitionArray[4]>Transition array #1:
0x320100000e5d <Symbol: (elements_transition_symbol)>: (transition to HOLEY_DOUBLE_ELEMENTS) -> 0x32010028cf69 <Map[16](HOLEY_DOUBLE_ELEMENTS)>
- prototype: 0x32010028c89d <JSArray[0]>
- constructor: 0x32010028c595 <JSFunction Array (sfi = 0x320100275b81)>
- dependent code: 0x320100000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
[1, 2, 3, 4, 5, 3.4]
```
- Ta thấy ngay lập tức *Elements kind* của mảng a đổi thành ```PACKED_DOUBLE_ELEMENTS```
- Khi ta thêm vào 1 kí tự thì *Elements kind* đổi thành ```PACKED_ELEMENTS```, ta thấy khi thêm một phần tử khác data type thì *Elements kind* sẽ đổi sang loạt tổng quát hơn để có thể mô tả dữ liệu trong mảng
- Khi dữ liệu trong mảng không nối tiếp nhau thì *Elements kind* sẽ đổi sang ```HOLY_ELEMENTS```, ví dụ như mảng trên đang có 6 phần từ từ index 0 đến 5 ta thêm vào mảng a ở index 8 thì trong mảng sẽ chứa các khoảng trống giữa các phần tử
- ##### Fast elements và Slow elements
- *Fast elements* là biểu diễn dữ liệu trong mảng liền kề nhau không có phần tử trống, phần tử không xác định, truy cập chậm hơn *Slow elements* nhưng tiết kiệm bộ nhớ hơn
- *Slow elements* thì ngược lại biểu diễn phần tử các nhau và có khoảng trống giữa các phần tử, truy cập nhanh hơn *Fast elements* nhưng tốn nhiều bộ nhớ hơn
### Properties
- Khi số lượng các thuộc tính trong object quá nhiều không thể lưu trữ trong cấu trúc bộ nhớ object sẽ được lưu trữ ở *properties*, vì ví dụ trên số lượng thuộc tính ít nên không có gì lưu trữ ở *properties*. Ở trường **All own properties (excluding elements)** ta thấy được các thuộc tính và *location : in-object* có nghĩa là được lưu trực tiếp trong cấu trúc bộ nhớ của object
### All own properties (excluding elements)
- Thông tin các thuộc tính như địa chỉ thuộc tính, địa chỉ các value, giá trị value và nơi lưu trữ thuộc tính đó
### Map
- **Map** đại diện cho ***Hidden Class***, **Map** mô tả cấu trúc của object và các thuộc tính của object đó được tổ chức trong bộ nhớ
- Đây là một cấu trúc của một **Map**
```javascript
0x36c900298f51: [Map] in OldSpace
- map: 0x36c9002816d9 <MetaMap (0x36c900281729 <NativeContext[291]>)>
- type: JS_OBJECT_TYPE
- instance size: 28
- inobject properties: 4
- unused property fields: 0
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x36c900298f29 <Map[28](HOLEY_ELEMENTS)>
- prototype_validity cell: 0x36c900000a89 <Cell value= 1>
- instance descriptors (own) #4: 0x36c900048879 <DescriptorArray[4]>
- prototype: 0x36c9002825d9 <Object map = 0x36c900281c15>
- constructor: 0x36c90028211d <JSFunction Object (sfi = 0x36c900275161)>
- dependent code: 0x36c900000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
```
- Gồm các thông tin như: type, instance size, inobject properties, elements kind, back pointer ...
- Mô tả cách hoạt động của **Hidden Class** ở ví dụ trên

- *Hidden Class* sẽ xây dựng một cấu trúc object từ lúc rỗng đến khi thêm đủ các thuộc tính
- Mỗi class trong cấu trúc được gọi là 1 Map
- Ta tạo một object sau đó thêm một thuộc tính vào để xem cấu trúc của *Hidden class*
- Trong *Hidden Class* có ```DescriptorArray``` và ```TransitionArray```
- ```DescriptorArray``` là danh sách đầy đủ các thuộc tính của các class có cùng thông tin
- ```TransitionArray```là một danh sách phản ánh sự thay đổi của đối tượng trong object như thêm, xóa, ...
```javascript=
d8> let object = {a:"hello", b:10}
undefined
d8> %DebugPrint(object)
DebugPrint: 0x10a4000487d1: [JS_OBJECT_TYPE]
- map: 0x10a400298edd <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x10a4002825d9 <Object map = 0x10a400281c15>
- elements: 0x10a400000725 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x10a400000725 <FixedArray[0]>
- All own properties (excluding elements): {
0x10a400002b19: [String] in ReadOnlySpace: #a: 0x10a400298d99 <String[5]: #hello> (const data field 0), location: in-object
0x10a400002b29: [String] in ReadOnlySpace: #b: 10 (const data field 1), location: in-object
}
0x10a400298edd: [Map] in OldSpace
- map: 0x10a4002816d9 <MetaMap (0x10a400281729 <NativeContext[291]>)>
- type: JS_OBJECT_TYPE
- instance size: 20
- inobject properties: 2
- unused property fields: 0
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x10a400298e95 <Map[20](HOLEY_ELEMENTS)>
- prototype_validity cell: 0x10a400000a89 <Cell value= 1>
- instance descriptors (own) #2: 0x10a400048801 <DescriptorArray[2]>
- prototype: 0x10a4002825d9 <Object map = 0x10a400281c15>
- constructor: 0x10a40028211d <JSFunction Object (sfi = 0x10a400275161)>
- dependent code: 0x10a400000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
{a: "hello", b: 10}
```
- Khi ta tạo object chứa 2 thuộc tính ```a```, ```b```, ta thấy địa chỉ map là ```0x10a400298edd``` ,các thuộc tính được lưu ở ```in-object```
```javascript=
d8> object.c = "haha"
"haha"
d8> %DebugPrint(object)
DebugPrint: 0x10a4000487d1: [JS_OBJECT_TYPE]
- map: 0x10a400299c51 <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x10a4002825d9 <Object map = 0x10a400281c15>
- elements: 0x10a400000725 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x10a40004a7a1 <PropertyArray[3]>
- All own properties (excluding elements): {
0x10a400002b19: [String] in ReadOnlySpace: #a: 0x10a400298d99 <String[5]: #hello> (const data field 0), location: in-object
0x10a400002b29: [String] in ReadOnlySpace: #b: 10 (const data field 1), location: in-object
0x10a400002b39: [String] in ReadOnlySpace: #c: 0x10a400299b99 <String[4]: #haha> (const data field 2), location: properties[0]
}
0x10a400299c51: [Map] in OldSpace
- map: 0x10a4002816d9 <MetaMap (0x10a400281729 <NativeContext[291]>)>
- type: JS_OBJECT_TYPE
- instance size: 20
- inobject properties: 2
- unused property fields: 2
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x10a400298edd <Map[20](HOLEY_ELEMENTS)>
- prototype_validity cell: 0x10a400299c79 <Cell value= 0>
- instance descriptors (own) #3: 0x10a40004a76d <DescriptorArray[3]>
- prototype: 0x10a4002825d9 <Object map = 0x10a400281c15>
- constructor: 0x10a40028211d <JSFunction Object (sfi = 0x10a400275161)>
- dependent code: 0x10a400000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
{a: "hello", b: 10, c: "haha"}
```
- Khi ta thêm một thuộc tính thì ta thấy map thay đổi thành ```0x10a400299c51``` và ```back pointer``` trỏ đến class phía trước trùng với pointer trước khi thêm ```0x10a400298edd```
- Ta thấy ```location``` ở ```properties[0]```, và thông tin ở ```properties: 0x10a40004a7a1 <PropertyArray[3]>``` cho ta biết ```properties``` đang lưu trữ thuộc tính. Nhưng vì sao kích thước array là 3, có thể là cơ chế cấp phát bộ nhớ của V8 để có thể tối ưu truy cập??. Ta dùng ```%DebugPrintPtr``` để xem chi tiết thông tin tại pointer đó
```javascript
d8> %DebugPrintPtr(0x10a40004a7a1)
DebugPrint: 0x10a40004a7a1: [PropertyArray]
- map: 0x10a400000999 <Map(PROPERTY_ARRAY_TYPE)>
- length: 3
- hash: 0
0: 0x10a400299b99 <String[4]: #haha>
1-2: 0x10a400000069 <undefined>
0x10a400000999: [Map] in ReadOnlySpace
- map: 0x10a4000004cd <MetaMap (0x10a400000085 <null>)>
- type: PROPERTY_ARRAY_TYPE
- instance size: variable
- elements kind: HOLEY_ELEMENTS
- enum length: invalid
- stable_map
- back pointer: 0x10a400000069 <undefined>
- prototype_validity cell: 0
- instance descriptors (own) #0: 0x10a400000759 <DescriptorArray[0]>
- prototype: 0x10a400000085 <null>
- constructor: 0x10a400000085 <null>
- dependent code: 0x10a400000735 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
```
- Ta thấy thuộc tính ```c``` được lưu trữ trong ```PropertyArray```