V8引擎工作原理

235 阅读2分钟

V8引擎工作原理

1.V8引擎是干什么的?

V8的工作是js代码运行需要翻译为CPU指令。

2.V8工作过程
  1. Blink将js源码交给V8引擎

  2. Stream对js源码编码

  3. Scanner进行词法分析,将代码转为token

  4. token转化为AST树

    • Parser将tokens直接转化为AST树

    • PreParser(预编译)

      • 有些代码不是一开始就运行,加载其会影响网站的运行效率,V8利用Lazy Parsing(延迟解析)
  5. AST树通过ignition转化为字节码

  6. 执行代码

overview.svg

图1 V8工作过程

注释
  • token是什么?

  • Lazy Parsing是什么?

    有些代码不是一开始就运行,将这些代码进行预解析,只解析出需要它的那一部分

    e.g

    function out(){
        function inner()
    }
    

    这种情况就会对inner进行预解析

  • AST树是什么?抽象语法树,类似于下图的数据结构(与json类似)

图片.png 图2 Token树示例

图片.png

图3 AST树示例

可以登录这个网站查看对应程序的AST树和Tokenesprima.org/demo/parse.…

js执行过程

示例 1

var age =18;
console.log(age);
var num1 =10;
var num2 =3;

上面这段代码

  1. V8解析(parse)上述代码会在堆里面产生GlobalObject(全局对象)

    var GlobalObject = {
        string: "类",
        data: "类",
        setTimeout: '函数',
        setInterval: '函数',
        window: GlobalObject,
        ...
        age: undefine,
        num1: undefine,
        num2: undefine,
    }
    
  2. 在执行上下文(Execution Context Stack,简称ECS)中构建全局上下文(Global Execution Context,简称GEC),在GEC对变量进行赋值以及执行函数。

    1. 先赋值age=18
    2. 执行console.log(age);
    3. ...以此类推

注释GlobalObject也是在GEC中构建的

图片.png

示例2

var age =18;
function foo(age1){
    var res = age1;
    console.log(res);    
}
foo(18)
var num1 =10;
  1. V8解析(parse)上述代码会在堆里面产生GlobalObject(全局对象)

    这里foo是一个地址

     var GlobalObject = {
        string: "类",
        data: "类",
        setTimeout: '函数',
        setInterval: '函数',
        window: GlobalObject,
        ...
        age: undefine,
        foo: 0xa00,
        num1: undefine,
    }
    

图片.png

  1. 执行代码

    1. 给age赋值为18(此时VO->GO)

    2. 执行函数foo(18)

      1. GEC构建活动对象(AO, activation object)

        AO{
            arguments:[age1=18],
            res: undefine
        }
        
      2. GEC构建FEC(函数执行上下文)(VO->AO)

图片.png

    5.  执行代码块,对res进行赋值...

总结

V8引擎首先对源码进行Parse(解析)生成token,然后对token进行编码生产 AST(Abstract Syntax Tree)抽象语法树,然后AST通过ignition转化为字节码,最后执行代码