12 字节码:解释器如何解释执行字节码
解释器可以直接解释执行字节码,也可以将字节码编译为二进制代码,然后再执行二进制机器代码。
早期的 V8 为了提高执行速度,直接将 JavaScript 代码编译成机器代码:
基线编译器,负责将 JavaScript 代码编译为没有优化过的机器代码。优化编译器,负责将一些热点代码(执行频繁的代码)优化为执行效率更高的机器代码。
机器代码缓存
JavaScript 代码在浏览器中执行,编译占用了很大一部分时间,浏览器中再次打开相同的页面,页面中的 JavaScript 文件没有被修改,再次编译之后的二进制代码也会保持不变。把二进制代码保存在内存中,重用它们完成后续的调用,省去再次编译的时间。
V8 的两种代码缓存策略:
- V8 第一次执行一段代码时,编译源 JavaScript 代码,并将编译后的二进制代码缓存在内存中,(内存缓存 in-memory cache)。通过 JavaScript 源文件的字符串在内存中查找对应的编译后的二进制代码。
- 将代码缓存到硬盘上,即使关闭了浏览器,下次重新打开浏览器再次执行相同代码时,也可以直接重复使用编译好的二进制代码。
字节码降低了内存占用
二进制代码所占用的内存空间是 JavaScript 代码的很多倍,在移动设备中占用过多的内存,会导致 Web 应用的速度大大降低。
虽然采用字节码在执行速度上稍慢于机器代码,但整体上权衡利弊,采用字节码是最优方式。