为什么要创建多个单形态缓存而不是一个多态缓存



我正在阅读这篇关于单态性的文章,其中有以下代码片段:

function ff(b, o) {
  if (b) {
    return o.x
  } else {
    return o.x
  }
}
ff(true, { x: 1 })
ff(false, { x: 2, y: 0 })
ff(true, { x: 1 })
ff(false, { x: 2, y: 0 })

函数ff中有多少个属性访问内联缓存?什么是他们所处的状态?答案:有两个缓存,都是单态的,因为每个缓存只能看到一个形状的对象。

我认为会有一个多态的,因为作者早些时候显示:

f({ x: 4, y: 1 }) // polymorphic, degree 2
f({ x: 5, z: 1 }) // polymorphic, degree 3
f({ x: 6, a: 1 }) // polymorphic, degree 4
f({ x: 7, b: 1 }) // megamorphic

函数被传递给不同结构的对象,它们将单形态缓存变为多形态缓存。为什么与所讨论的例子不同?

这些"内联缓存"存在于代码中每个不同的属性引用中。因此在功能上:

function ff(b, o) {
  if (b) {
    return o.x   // IC here
  } else {
    return o.x   // IC here
  }
}

这两个return语句都有自己的内联缓存。由于在示例中调用函数的方式,第一个return仅发生在第一个形状的对象中,第二个仅发生在第二个形状的物体中。因此,每个高速缓存(在对ff()的那四次调用之后(将只看到一个形状。

第五次调用如下函数后:

ff(true, { x: 1, z: 10 });

第一个IC将看到两个形状,因此其IC将是多态的。

每个属性访问o.x都有自己的IC,即使同一对象的同一属性被多次访问也是如此。

如果您运行node --trace-ic someScript.js,您可以看到IC属于哪个行号。

最新更新