(1)v8简介
2021-07-26 本文已影响0人
sullay
V8 并没有采用某种单一的技术,而是混合编译执行和解释执行这两种手段,我们把这种混合使用编译器和解释器的技术称为 JIT(Just In Time)技术。
这是一种权衡策略,因为这两种方法都各自有各自的优缺点,解释执行的启动速度快,但是执行时的速度慢,而编译执行的启动速度慢,但是执行时的速度快。你可以参考下面完整的 V8 执行 JavaScript 的流程图:
初始化基础环境
- JavaScript 全局执行上下文就包含了执行过程中的全局信息,比如一些内置函数,全局变量等信息;
- 全局作用域包含了一些全局变量,在执行过程中的数据都需要存放在内存中;
- 而 V8 是采用了经典的堆和栈的内存管理模式,所以 V8 还需要初始化内存中的堆和栈结构;
- 另外,想要我们的 V8 系统活起来,还需要初始化消息循环系统,消息循环系统包含了消息驱动器和消息队列,它如同 V8 的心脏,不断接受消息并决策如何处理消息。
解析源码生成 AST(抽象语法树)
d8 --print-ast test.js
[generating bytecode for function: ]
--- AST ---
FUNC at 0
. KIND 0
. LITERAL ID 0
. SUSPEND COUNT 0
. NAME ""
. INFERRED NAME ""
. DECLS
. . VARIABLE (0x7fd47200fc90) (mode = VAR, assigned = true) "test"
. BLOCK NOCOMPLETIONS at -1
. . EXPRESSION STATEMENT at 11
. . . INIT at 11
. . . . VAR PROXY unallocated (0x7fd47200fc90) (mode = VAR, assigned = true) "test"
. . . . LITERAL "sullay"
解析源码生成作用域
d8 --print-scopes test.js
Global scope:
global { // (0x7fe60004e248) (0, 19)
// will be compiled
// 1 stack slots
// temporary vars:
TEMPORARY .result; // (0x7fe60004e5a8) local[0]
// local vars:
VAR test; // (0x7fe60004e490)
}
依据AST和作用域生成字节码
d8 --print-bytecode test.js
[generated bytecode for function: (0x16d008292e4d <SharedFunctionInfo>)]
Bytecode length: 18
Parameter count 1
Register count 3
Frame size 24
OSR nesting level: 0
Bytecode Age: 0
0x16d008292ed6 @ 0 : 13 00 LdaConstant [0]
0x16d008292ed8 @ 2 : c2 Star1
0x16d008292ed9 @ 3 : 19 fe f8 Mov <closure>, r2
0x16d008292edc @ 6 : 64 4f 01 f9 02 CallRuntime [DeclareGlobals], r1-r2
0x16d008292ee1 @ 11 : 13 01 LdaConstant [1]
0x16d008292ee3 @ 13 : 23 02 00 StaGlobal [2], [0]
0x16d008292ee6 @ 16 : 0e LdaUndefined
0x16d008292ee7 @ 17 : a8 Return
Constant pool (size = 3)
0x16d008292ea1: [FixedArray] in OldSpace
- map: 0x16d008002205 <Map>
- length: 3
0: 0x16d008292e95 <FixedArray[1]>
1: 0x16d008292e2d <String[6]: #sullay>
2: 0x16d00820c015 <String[4]: #test>
Handler Table (size = 0)
Source Position Table (size = 0)
优化热点代码为二进制的机器代码
生成字节码之后,解释器会解释执行这段字节码,如果重复执行了某段代码,监控器就会将其标记为热点代码,并提交给编译器优化执行。
d8 --trace-opt test.js
反优化生成的二进制机器代码
JavaScript 是一门动态语言,在运行过程中,某些被优化的结构可能会被 V8 动态修改了,这会导致之前被优化的代码失效,如果某块优化之后的代码失效了,那么编译器需要执行反优化操作
d8 --trace-deopt test.js