likes
comments
collection
share

V8引擎详解(四)——字节码是如何执行的

作者站长头像
站长
· 阅读数 0

前言

字节码的执行

一、基于寄存器

Ignition引擎可以对字节码进行解释执行,那就是说他的功能类似于Java的JVM,本质上就是一个虚拟机。 虚拟机通常有两种分别是基于Stack(栈)的和基于Register(寄存器)的, 比如基于Stack的虚拟机有JVM,是一种比较广泛的实现方法,而我们V8引擎中的Ignition是基于Register的,也就是基于寄存器的虚拟机,通常基于Register的虚拟机比基于Stack的虚拟机执行的更快,但是指令相对较长。

Ignition是一个带有累加器(accumulator)的寄存器,我举一个小例子大家就明白了。 我们先抛开字节码看这段简单的代码如何计算出结果。

var x = 100;
var y = x +10;
x = x * y;

运用累加寄存器的大致运行流程如下:

V8引擎详解(四)——字节码是如何执行的

这种就是我们基于寄存器虚拟机运行的一个大致流程,简单来说就是创建一块虚拟空间来保存参数、中间计算结果。

二、通过官方案例解读字节码

接下来会通过Google官方PPT上面的一段案例来解读V8上字节码的执行。我会逐图配上一些文字注解帮助大家阅读。

  • 先将源码转换成字节码

    V8引擎详解(四)——字节码是如何执行的

  • 进行函数 f 的初始化工作

    V8引擎详解(四)——字节码是如何执行的

  • 将小整数 -100 存储到累加器中,LdaSmi 可以理解为一个定义好的handle函数 后面接的 #100 就是这个函数的参数

    V8引擎详解(四)——字节码是如何执行的

  • 将a2中存储的150和累加器中的值求和,并将结果存于累加器 。

    V8引擎详解(四)——字节码是如何执行的

  • 将累加器中存储的50保存到寄存器r0中,此时r0的值为50。

    V8引擎详解(四)——字节码是如何执行的

  • 将寄存器a1也就是参数b的值存储到累加器中,此时累加器值为2。(a0、a1、a2 也是寄存器)

    V8引擎详解(四)——字节码是如何执行的

  • 将寄存器r0中的值和累加器中的值求乘积,并将结果存于累加器。

    V8引擎详解(四)——字节码是如何执行的

  • 将寄存器a0中的值和累加器中的值求和,并将结果存于累加器。

    V8引擎详解(四)——字节码是如何执行的

  • Return (包括上面的语句)本身都是定义好的handle函数,Return代表的就是将累加器中的值返回。

    V8引擎详解(四)——字节码是如何执行的

(随着v8版本的更新,不同的版本生成的字节码结构可能有细微差别,但是这些定义好的函数一般不会有太大变化)

通过这个例子相信大家可以大概了解字节码的执行,但是v8定义的关键字可不止例子中这一点(完整的放在附录中了),在学习的过程中开始很多关键字也确实不好理解,不过我们可以通过自己写一些简单的js代码然后生成字节码,因为我们已知js的执行结果,可以通过倒推的方式来理解字节码。

总结

本文主要带大家简单了解了v8是如何解释执行字节码的。

有人问我,作为一个前端学习这些东西到底有什么用?这些东西还没那么容易理解,有这个时间不如多刷两道题、看看面试问题、看看框架。 从短期来看学习V8引擎并不能明显的提高面试的能力,但是万丈高楼平地起,想成为一个优秀的前端程序员v8引擎的学习能帮助你更加深刻的理解js中的一些事情,比如通过对AST的学习更加了解了babel的工作原理,为什么一个页面第二次加载比第一次快(不仅仅是静态资源的缓存哦),为什么node选择了v8作为js引擎,如果不能深入的了解一下,也只是在复述别人得出的结论而已。

我在写本章的时候,想起来我面试被问的一道问题switch为什么比if else快,当时回家查了一下相关文章发现有人说switch跳表巴拉巴拉的,我专门转成了字节码看了一下,发现起码在正常的v8环境中switch比if else快纯属扯淡,从字节码上发现,绝大部分条件下两个几乎都是一样快,如果有兴趣可以自己玩一下。

V8字节码表

V8引擎详解(四)——字节码是如何执行的

参考文章

docs.google.com/presentatio… time.geekbang.org/column/arti…

系列文章