浅析一下V8引擎的原理到底是什么呢?

1,554 阅读3分钟

前言:v8引擎本身的源码是非常复杂的,大概有超过100w行c++的代码,这里不做具体解析,只是浅析一下V8引擎的的原理是怎样的,如何去执行js代码?

我们来看下官方对V8引擎的定义:

image.png 简单说一下就是:V8引擎是C++编写的开源引擎,用于Chrome和Node.js去执行js代码,可以独立运行,也可以嵌入在C++应用程序中

那V8引擎是如何去执行js代码?

image.png

  1. 首先javaScript源代码,会经过paser模块,被解析成AST抽象语法树(因为解释器并不认识javaScript代码)
    • 那在转成parse的这个过程中发生了什么呢?其实主要是词法分析和语法分析
      词法分析:会把代码分成一个个不能细分的单词(token),这些token组成tokens数组 如 const name="foo" 分别是 const、name、foo,这个过程是词法分析,按照单词的构成规则来拆分字符串成单词。我们来看下图
    • 语法分析:把 token 进行组装,生成 AST,这个过程是语法分析,按照不同的语法结构,来把一组单词组合成对象。我们来一起看下图
      这里附上AST语法解析官网链接 :传送门AST语法解析官网

image.png
name对应:

 "id": {
            "type": "Identifier",
            "start": 6,
            "end": 10,
            "name": "name"
          },

foo对应:

"init": {
            "type": "Literal",
            "start": 11,
            "end": 16,
            "value": "foo",
            "raw": "\foo\""
          }
  1. 第二步会经过lgnition解释器,将AST抽象语法树解释成字节码bytecode
    • 如果代码只执行一遍是直接通过lgniton解释成字节码,如果一个函数被调用很多次,那这个函数会被标记成热点函数(hot func),会经过turbofan,转成优化之后的机器码
    • 如果一个热点函数在调用的过程中,类型发生了改变,那么还是要经过lgnition来进行deoptimited反优化,有机器码再转为字节码,然后再转为机器码进行运行由
v8引擎的架构

有三大模块,分别是:

  • parse模块
    将js源代码解析成AST抽象语法树
  • lgnition
    lgnition解释器:将AST抽象语法树解释成字节码
    同时收集turbofan所需要的优化信息
  • turtofan
    turbofan是一个编译器:可以将字节码编译成CPU直接运行的机器码
    如果一个函数被多次调用,那么会标记成热点函数,由turbofan直接编译成优化后的机器码来提升性能
问答环节

追问:这是为什么不直接转成机器码而要先转成字节码呢?
因为无法确定这个代码会运行在怎样的环境上(windows,mac,linux),不同环境的cpu架构不同,不同cpu架构能执行的机器指令不同,所以无法确定机器指令,所以才转化为字节码。字节码可以跨平台,转化为机器指令后就可以运行了

追问:这里抛出一个问题,为什么不通过lgnition直接编译成字节码呢?
因为lgnition解释器并不能直接认识s代码,需要先经过parse模块解析成抽象语法树

预告:
下个章节说JS的执行过程和执行上下文