V8如果属性类型不同,则两个相同类型对象的隐藏类不相同

时间:2017-11-30 19:10:33

标签: javascript javascript-objects v8

我已经阅读了V8中隐藏的类,并在d8调试器shell中进行了一些测试。

function Vector(a, b) {
  this.a = a;
  this.b = b;
}

var x = new Vector(1, 2);
var y = new Vector(1, 3);
var z = new Vector(1, 'a');

print( %HaveSameMap( x, y ) ); //true
print( %HaveSameMap( x, z ) ); //false
x.b;
print( %HaveSameMap( x, z ) ); //true
print( %HaveSameMap( y, z ) ); //false
y.b;
print( %HaveSameMap( y, z ) ); //true

因为我们可以看到对象属性类型是否不同,所以在我们尝试访问类型不同的老对象中的属性之前,它们不共享它们的隐藏类。任何人都可以清楚地解释“幕后”发生了什么,也许它与内联缓存有关。

1 个答案:

答案 0 :(得分:4)

V8开发者在这里。简而言之,正在发生的事情是“隐藏类”不仅存储属性的存在信息,还存储有关其值的(相对粗粒度)类型信息。为了避免有太多不同的隐藏类,在触摸对象时它们会被合并。

在你的例子中:

var x = new Vector(1, 2);
var y = new Vector(1, 3);

xy现在都有一个隐藏的类HC1知道“我有一个属性.b,它的值总是一个小整数(又名Smi)“。但后来发生了这种情况:

var z = new Vector(1, 'a');

因此z需要该隐藏类的更新版本,因为其.b的值是一个字符串。 V8目前还没有记住“值可以是整数或字符串”;相反,它只是丢弃类型信息。因此,z会获得一个新的隐藏类HC2,它知道“我有一个属性.b(但我对它的价值一无所知,它可能是任何东西)” 。创建此隐藏课程HC2后,HC1会被标记为“过时”;但为了节省时间,我们没有努力使用HC1查找和更新对象。当你运行

x.b;

然后V8必须查看x及其隐藏的类HC1,并注意到HC1已被标记为“过时”,因此它会找到更新后的版本{{1并更新HC2以使用它。

优化像JavaScript这样的动态语言非常复杂; - )