V8概览

作者: JunhYan | 来源:发表于2021-01-06 16:18 被阅读0次

    本文主要从两个维度简要介绍下V8
    1、V8的源码结构(version 8.6)
    2、V8在运行流程上的衍变

    V8源码结构概览

    这个在某些目录的介绍上可能存在理解问题,需要在阅读源码过程中逐步完善

     v8
        |
        |_ _ _
            |_ _ _ _ include
            |       |
            |       |_ _ _ _  v8.h 所有v8提供的接口
            |
            |_ _ _ _ src
                    |
                    |_ _ _ _  api **对外接口
                    |
                    |_ _ _ _  asmjs **js汇编
                    |
                    |_ _ _ _  ast **虚拟语法树
                    |
                    |_ _ _ _  base **基础内容,如cpu 内存的处理
                    |
                    |_ _ _ _  builtins **内置处理
                    |
                    |_ _ _ _  common
                    |
                    |_ _ _ _  codegen ** (猜)ast到机器语言或bytecode到机器语言
                    |
                    |_ _ _ _  compiler ** (猜)ast到bytecode,之前是没有从ast到bytecode这一步骤的,2017年引入,Android移动端内存紧张(编译可配置)
                    |
                    |_ _ _ _  d8 **一个调试程序
                    |
                    |_ _ _ _  date
                    |
                    |_ _ _ _  debug
                    |
                    |_ _ _ _  deoptimizer
                    |
                    |_ _ _ _  diagnostics
                    |
                    |_ _ _ _  execution
                    |
                    |_ _ _ _  extensions
                    |
                    |_ _ _ _  flags
                    |
                    |_ _ _ _  handles
                    |
                    |_ _ _ _  heap **V8堆处理
                    |
                    |_ _ _ _  ic
                    |
                    |_ _ _ _  init **初始化
                    |
                    |_ _ _ _  inspector
                    |
                    |_ _ _ _  interpreter
                    |
                    |_ _ _ _  json
                    |
                    |_ _ _ _  libplatform
                    |
                    |_ _ _ _  libsampler
                    |
                    |_ _ _ _  logging
                    |
                    |_ _ _ _  numbers
                    |
                    |_ _ _ _  objects **js数据类型
                    |
                    |_ _ _ _  parsing **解析js源码
                    |
                    |_ _ _ _  profiler
                    |
                    |_ _ _ _  protobuf
                    |
                    |_ _ _ _  regexp
                    |
                    |_ _ _ _  roots
                    |
                    |_ _ _ _  runtime ** 运行时处理,lazy JIT
                    |
                    |_ _ _ _  sanitizer
                    |
                    |_ _ _ _  snapshot **快照,减少全局上下文创建时的CPU、内存消耗,V8使用了Snapshot技术,全局上下文初始化后,将目前堆内存序列化为字节代码,保存至磁盘文件,加载时,将该snapshot文件反序列化进内存
                    |
                    |_ _ _ _  strings
                    |
                    |_ _ _ _  tasks
                    |
                    |_ _ _ _  third_party
                    |
                    |_ _ _ _  torque  ** v8的TQ, CSA(c++写TurboFan(生成机器码的阶段)),TQ是用类似js(更像ts)代码编译成CSA
                    |
                    |_ _ _ _  tracing
                    |
                    |_ _ _ _  trap-handler
                    |
                    |_ _ _ _  utils
                    |
                    |_ _ _ _  wasm  **webAssembly
                    |
                    |_ _ _ _  zone
    

    V8 pipeline衍变

    主要介绍编译阶段的一些优化衍变,在生成AST前的优化比如lazy parse等单独介绍


    v8-pipelines.png

    V8执行js代码的整个流程
    Parser阶段其实分为了两个,一个是scanner,一个是parser,scanner用来做分词,根据输入的utf-16字符流解析Token,parser根据scanner的解析出的Token做语法的解析然后生成ast
    后面的部分是从ast到机器码的过程,可以看到有很多的分支,这个是一个整体的图,v8运行优化ast前变动不大,大部分是在ast之后的优化
    下面简单的介绍下这个过程


    pipe-2008.jpg
    上图是2008年最原始的版本,就是简单的把ast转换成简单优化的机器码
    pipe-2010.jpg

    上图在V8里面引入了crankshaft优化机制,这个优化主要是对于热点函数(就是经常用到的函数),从js code层面做优化,然后替换原来未优化的代码


    pipe-2015.jpg
    上图是2015年的一个优化,这个阶段可以看到引入了TurboFan,引入它的原因主要是crankshaft的一些限制,比如一些关键字try cache代码块里面的内容他没法优化,然后如果有新的语法,他需要针对不同的cpu架构写各自的优化策略,turbofan的引入就是为了解决这些问题的
    pipe-2016.jpg
    我觉得这个是2016年的一个过度版本,Crankshaft是不支持从ByteCode直接做优化的,而在这个版本中实现Turbofan可以支持从字节码来做优化,提供一个可选的方案。
    pipe-moblie.jpg
    这个是针对移动端支持的一个架构,正式引入了字节码,如果还是使用原来的架构,那编译完成的机器码会占用很多的内存,移动端的内存还是比较吃紧的,所以引入了这么一套架构,移动端编译V8的时候,可以使用带字节码的这一个流程,其实这个是一个用时间来换空间的解决方案,之前的架构直接从AST到机器码的性能大部分情况是比加入字节码要快很多的。
    pipe-2017.jpg
    这个是目前最后的一个版本。
    直接编译机器码的主要弊端:占用内存大,导致的问题就是不能全编译,大部分时候方法内部的执行逻辑都是在第一次运行时候懒加载(区分Lasy parse 和 Lasy compile)的,改成字节码中转后带来的另一个好处启动时间(区别于运行时间)缩短了。因为可以提前编译所有代码了,可以提前把字节码缓存。权衡利弊,走向了和js core一样的道路。

    相关文章

      网友评论

          本文标题:V8概览

          本文链接:https://www.haomeiwen.com/subject/veyvoktx.html