13 | 字节码(一):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
《图解 Google V8》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(32)
- 最新
- 精选
- chris字节码是平台无关的,机器码针对不同的平台都是不一样的
作者回复: 是的
2020-04-1434 - Zzzzz为什么不直接解释执行 JavaScript,省去生成字节码不是更降低内存消耗?
作者回复: 这是编译标准流程
2020-06-1323 - luckyone好看,真香。第一步都要转成ast?不同的话解释执行跟二进制执行,现在大多数语言都是虚拟机执行吧java c# n多动态语言。 编译的c c++ go
作者回复: 对的
2020-04-141 - Geek_177f82原文中说“由于字节码占用的空间远小于二进制代码,所以浏览器就可以实现缓存所有的字节码,而不是仅仅缓存顶层的字节码。”那么v8是否已经实现缓存所有的字节码?如果已经实现,那么是怎么实现的呢?由于惰性解析策略的限制他是怎么实现缓存所有字节码的呢?2020-04-21116
- mfistV8的Ignition编译产生字节码,运行一段时间后发现热点代码通过turbofan优化成机器码。他们都是JavaScript执行过程的中间产物,但是字节码消除了平台差异性,机器码是针对具体某一个运行设备的优化。不知道理解对不对,请老师指正2020-04-1416
- Javon Yan字节码,一般是在虚拟机上执行的代码,不是在最终的物理机器上执行的二进制代码。 机器代码,即二进制代码,不同CPU的机器二进制代码不同。 字节码占用空间小,二进制机器码占用空间大。 源码转换为字节码时间消耗较短,生成二进制码时间消耗较长。2020-08-255
- 咚咚咚东字节码是一种中间代码,解释器在执行字节码时,也需要把字节码转换成机器代码执行。 所以,字节码的编译速度快(毕竟不用一步直接编译到机器代码),体积小(中间代码肯定比最终代码简洁),但是执行效率慢(毕竟要再次由解释器解释执行)2021-01-254
- 大熊猫的五分裤有个问题希望老师能够帮忙解答一下,早期V8引擎中对JavaScript代码的编译是通过解析器和编译器实现的,并且解析生成的机器码会保存在内存中,这是否与JavaScript是门解释型语言这点相违背呢?这点我们该怎么理解呢?2020-08-213
- sugar提一个问题,从ignition解析器生成的字节码中发现热点代码 用turboFan进行优化,这个热点代码会是以函数闭包的维度吗?还是比这更细的粒度? 然后在chrome和node.js等常规的js运行环境里,是否有什么办法干预 或者主动告知v8 我想对哪部分代码做优化,哪部分不需要优化?2020-04-153
- 奕机器代码 是和具体的机器CPU型号相关的, 而字节码是 机器码上面的抽象和机器无关2020-04-142
收起评论