(1)v8简介

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 )]
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 , 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 
 - length: 3
           0: 0x16d008292e95 
           1: 0x16d008292e2d 
           2: 0x16d00820c015 
Handler Table (size = 0)
Source Position Table (size = 0)

优化热点代码为二进制的机器代码

生成字节码之后,解释器会解释执行这段字节码,如果重复执行了某段代码,监控器就会将其标记为热点代码,并提交给编译器优化执行。

d8 --trace-opt test.js

反优化生成的二进制机器代码

JavaScript 是一门动态语言,在运行过程中,某些被优化的结构可能会被 V8 动态修改了,这会导致之前被优化的代码失效,如果某块优化之后的代码失效了,那么编译器需要执行反优化操作

d8 --trace-deopt test.js

你可能感兴趣的:((1)v8简介)