lihongxun945/myblog

JS 引擎基础:Shapes 和 ICs

lihongxun945 opened this issue · 0 comments

本文是一篇读书笔记, 原文地址 JavaScript engine fundamentals: Shapes and Inline Caches

讲的主要是JS引擎中的两个重要部分: Shapes 和 ICs。这两部分是JS引擎对对象存储的实现方式,了解这部分可以帮我更好的理解JS的底层存储逻辑,也可以为以后优化代码提供思路。

JS 引擎的工作原理

  1. JS源码会首先被解析成一棵抽象语法树 AST
  2. 然后会由一个解释器将这棵语法树解析成字节码,同时,会保存一些metadata
  3. 一个优化引擎会读取 metadata和字节码,然后经过一些猜测来优化代码
  4. 如果猜错了,会进行 deoptimize

上图是V8的工作流程

Shapes

Shapes 是JS引擎内部存储对象的一种方式,所有的引擎都会有这种方式,不过他们各自的叫法不同。

如上图所示,如果我们定义了一个对象 object,那么他会生成一个对应的 Shape,这个Shape 其实就是用来存储对象的KV值的。Shape中会以偏移位置来记录每个值。

如果两个对象的key不同,那么他们他们对应的Shape就不同。不同的Shape会形成一个树状的结构 Shape Tree,如下图所示:

ICs

ICs 是 inline Caches的缩写,为什么要有Shape呢?为了更快的读写对象的属性。而ICs就是对象属性存储的地方。如下图所示:

当我们读取一个对象的属性的时候,会被解析成对ICs 的一个偏移地址的读取,因为没有查找过程,所以这个操作是非常高效的。

Arrays

我们了解了对象的存储。那么数组是怎么存储的呢?

其实数组的存储分两部分,首先,数组本身是一个对象,他有一个 length 属性,这个带有 length 属性的对象会被当做一个正常的对象存储起来。

然后,数组的内容会有一个单独的数据结构来存储:

这样当我们查找数组中的元素的时候,直接根据 index 计算出偏移值,在 Elements 中就可读写。

如果我们把数组中的 indices 的定义给修改了会怎么样呢? 如下图所示:

我们把 数组的 0 变成了一个key,那么 以前按照偏移存储的数据结构 Elements 将被变成 一个字典 Dictionary Elements ,这样数组就变成一个对象了,而读写性能也会大幅下降。