内联缓存 - ParadiseGuo/JavascriptLearning GitHub Wiki
工作原理简述: 内联缓存的详解
内联缓存依赖于发生在相同类型的对象上的相同方法的重复调用的观察上。
V8 维护一个在最近的方法调用中作为参数传递的对象类型的缓存,并使用这些信息来预测将来作为参数传递的对象的类型。如果V8能够很好地假定传递给方法的对象类型,那么它可以绕过如何访问对象的属性的过程,而是将之前查找到的信息用于对象的隐藏类。
那么隐藏类和内联缓存的概念如何相关呢?无论何时在特定对象上调用方法时,V8 引擎都必须执行对该对象的隐藏类的查找,以确定访问特定属性的偏移量。在同一个隐藏类的两次成功的调用之后,V8 省略了隐藏类的查找,并简单地将该属性的偏移量添加到对象指针本身。对于该方法的所有下一次调用,V8 引擎都假定隐藏的类没有更改,并使用从以前的查找存储的偏移量直接跳转到特定属性的内存地址。这大大提高了执行速度。
内联缓存也是为什么相同类型的对象可以共享隐藏类非常重要的原因。如果你创建了两个相同类型的对象和不同的隐藏类(就像我们之前的例子中那样),V8 将不能使用内联缓存,因为即使两个对象是相同的类型,它们相应的隐藏类为其属性分配不同的偏移量。
当然,Javascript是一种动态类型化的语言,如果发现对对象的隐藏类的假设是不正确的,在这种情况下,V8将会“去优化”并恢复到方法调用的原始版本, 这个时候隐藏类会被检查。
Example:
this.puppies[0]
push [ebp+0x8]
mov eax,[ebp+0xc]
mov edx, eax
mov ecx, 0x60b55dd1
call LoadIC_Initialize ;; this.puppies
push [ebp+0x8]
mov eax,[ebp+0xc]
mov edx, eax
mov ecx, 0x60b55dd1
call 0x311286e0 ;; this.puppies