图解 Google V8
李兵
前盛大创新院高级研究员
26763 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

13 | 字节码(一):V8为什么又重新引入字节码?

机器代码和字节码的异同
降低代码复杂度
提升代码启动速度
降低内存占用
二进制代码缓存策略
硬盘缓存
内存缓存
优化编译器
基线编译器
抽象语法树(AST)
解释执行字节码或编译为二进制代码
编译为字节码
思考题
字节码优势
字节码降低内存占用
机器代码缓存
早期V8执行流程
介绍V8的编译流水线
V8虚拟机

该思维导图由 AI 生成,仅供参考

你好,我是李兵。
在第一节课我们就介绍了 V8 的编译流水线,我们知道 V8 在执行一段 JavaScript 代码之前,需要将其编译为字节码,然后再解释执行字节码或者将字节码编译为二进制代码然后再执行。
所谓字节码,是指编译过程中的中间代码,你可以把字节码看成是机器代码的抽象,在 V8 中,字节码有两个作用:
第一个是解释器可以直接解释执行字节码 ;
第二个是优化编译器可以将字节码编译为二进制代码,然后再执行二进制机器代码。
虽然目前的架构使用了字节码,不过早期的 V8 并不是这样设计的,那时候 V8 团队认为这种“先生成字节码再执行字节码”的方式,多了个中间环节,多出来的中间环节会牺牲代码的执行速度。
于是在早期,V8 团队采取了非常激进的策略,直接将 JavaScript 代码编译成机器代码。其执行流程如下图所示:
早期V8执行流水线
观察上面的执行流程图,我们可以发现,早期的 V8 也使用了两个编译器:
第一个是基线编译器,它负责将 JavaScript 代码编译为没有优化过的机器代码。
第二个是优化编译器,它负责将一些热点代码(执行频繁的代码)优化为执行效率更高的机器代码。
了解这两个编译器之后,接下来我们再来看看早期的 V8 是怎么执行一段 JavaScript 代码的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

V8引入字节码的原因是为了解决早期直接将JavaScript代码编译为机器代码所带来的内存占用和执行速度问题。通过将JavaScript代码编译为字节码,V8可以实现内存缓存和优化执行,从而提升代码的启动速度和降低复杂度。采用字节码虽然在执行速度上略慢于机器代码,但相较于机器代码,字节码占用的空间更小,可以实现缓存所有的字节码,而不仅仅是顶层的字节码。这种优化带来的好处是降低了内存占用,提升了代码的启动速度,并降低了代码的复杂度,而牺牲的仅仅是一点执行效率。V8的这一优化策略为浏览器中JavaScript代码的执行速度和内存占用带来了显著的改善。早期的V8为了提升代码的执行速度,直接将JavaScript源代码编译成了没有优化的二进制的机器代码,如果某一段二进制代码执行频率过高,那么V8会将其标记为热点代码,热点代码会被优化编译器优化,优化后的机器代码执行效率更高。不过随着移动设备的普及,V8团队逐渐发现将JavaScript源码直接编译成二进制代码存在两个致命的问题:编译时间过久,影响代码启动速度;缓存编译后的二进制代码占用更多的内存。这两个问题无疑会阻碍V8在移动设备上的普及,于是V8团队大规模重构代码,引入了中间的字节码。字节码的优势有如下三点:生成字节码的时间很短;字节码占用内存不多,缓存字节码会大大降低内存的使用;采用字节码,可以简化程序的复杂度,使得V8移植到不同的CPU架构平台更加容易。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(32)

  • 最新
  • 精选
  • chris
    字节码是平台无关的,机器码针对不同的平台都是不一样的

    作者回复: 是的

    2020-04-14
    34
  • Zzzzz
    为什么不直接解释执行 JavaScript,省去生成字节码不是更降低内存消耗?

    作者回复: 这是编译标准流程

    2020-06-13
    2
    3
  • luckyone
    好看,真香。第一步都要转成ast?不同的话解释执行跟二进制执行,现在大多数语言都是虚拟机执行吧java c# n多动态语言。 编译的c c++ go

    作者回复: 对的

    2020-04-14
    1
  • Geek_177f82
    原文中说“由于字节码占用的空间远小于二进制代码,所以浏览器就可以实现缓存所有的字节码,而不是仅仅缓存顶层的字节码。”那么v8是否已经实现缓存所有的字节码?如果已经实现,那么是怎么实现的呢?由于惰性解析策略的限制他是怎么实现缓存所有字节码的呢?
    2020-04-21
    1
    16
  • mfist
    V8的Ignition编译产生字节码,运行一段时间后发现热点代码通过turbofan优化成机器码。他们都是JavaScript执行过程的中间产物,但是字节码消除了平台差异性,机器码是针对具体某一个运行设备的优化。不知道理解对不对,请老师指正
    2020-04-14
    1
    6
  • Javon Yan
    字节码,一般是在虚拟机上执行的代码,不是在最终的物理机器上执行的二进制代码。 机器代码,即二进制代码,不同CPU的机器二进制代码不同。 字节码占用空间小,二进制机器码占用空间大。 源码转换为字节码时间消耗较短,生成二进制码时间消耗较长。
    2020-08-25
    5
  • 咚咚咚东
    字节码是一种中间代码,解释器在执行字节码时,也需要把字节码转换成机器代码执行。 所以,字节码的编译速度快(毕竟不用一步直接编译到机器代码),体积小(中间代码肯定比最终代码简洁),但是执行效率慢(毕竟要再次由解释器解释执行)
    2021-01-25
    4
  • 大熊猫的五分裤
    有个问题希望老师能够帮忙解答一下,早期V8引擎中对JavaScript代码的编译是通过解析器和编译器实现的,并且解析生成的机器码会保存在内存中,这是否与JavaScript是门解释型语言这点相违背呢?这点我们该怎么理解呢?
    2020-08-21
    3
  • sugar
    提一个问题,从ignition解析器生成的字节码中发现热点代码 用turboFan进行优化,这个热点代码会是以函数闭包的维度吗?还是比这更细的粒度? 然后在chrome和node.js等常规的js运行环境里,是否有什么办法干预 或者主动告知v8 我想对哪部分代码做优化,哪部分不需要优化?
    2020-04-15
    3
  • 机器代码 是和具体的机器CPU型号相关的, 而字节码是 机器码上面的抽象和机器无关
    2020-04-14
    2
收起评论
显示
设置
留言
32
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部