V8引擎工作原理
1.V8引擎是干什么的?
V8的工作是js代码运行需要翻译为CPU指令。
2.V8工作过程
-
Blink将js源码交给V8引擎
-
Stream对js源码编码
-
Scanner进行词法分析,将代码转为token
-
token转化为AST树
-
Parser将tokens直接转化为AST树
-
PreParser(预编译)
- 有些代码不是一开始就运行,加载其会影响网站的运行效率,V8利用Lazy Parsing(延迟解析)
-
-
AST树通过ignition转化为字节码
-
执行代码
注释
-
token是什么?
-
Lazy Parsing是什么?
有些代码不是一开始就运行,将这些代码进行预解析,只解析出需要它的那一部分
e.g
function out(){ function inner() }这种情况就会对inner进行预解析
-
AST树是什么?抽象语法树,类似于下图的数据结构(与json类似)
图2 Token树示例
图3 AST树示例
可以登录这个网站查看对应程序的AST树和Tokenesprima.org/demo/parse.…
js执行过程
示例 1
var age =18;
console.log(age);
var num1 =10;
var num2 =3;
上面这段代码
-
V8解析(parse)上述代码会在堆里面产生GlobalObject(全局对象)
var GlobalObject = { string: "类", data: "类", setTimeout: '函数', setInterval: '函数', window: GlobalObject, ... age: undefine, num1: undefine, num2: undefine, } -
在执行上下文(Execution Context Stack,简称ECS)中构建全局上下文(Global Execution Context,简称GEC),在GEC对变量进行赋值以及执行函数。
- 先赋值age=18
- 执行console.log(age);
- ...以此类推
注释GlobalObject也是在GEC中构建的
示例2
var age =18;
function foo(age1){
var res = age1;
console.log(res);
}
foo(18)
var num1 =10;
-
V8解析(parse)上述代码会在堆里面产生GlobalObject(全局对象)
这里foo是一个地址
var GlobalObject = { string: "类", data: "类", setTimeout: '函数', setInterval: '函数', window: GlobalObject, ... age: undefine, foo: 0xa00, num1: undefine, }
-
执行代码
-
给age赋值为18(此时VO->GO)
-
执行函数foo(18)
-
GEC构建活动对象(AO, activation object)
AO{ arguments:[age1=18], res: undefine } -
GEC构建FEC(函数执行上下文)(VO->AO)
-
-
5. 执行代码块,对res进行赋值...
总结
V8引擎首先对源码进行Parse(解析)生成token,然后对token进行编码生产 AST(Abstract Syntax Tree)抽象语法树,然后AST通过ignition转化为字节码,最后执行代码