V8内联缓存如何与删除和计算属性访问一起使用?

时间:2017-06-05 11:17:19

标签: javascript v8

https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access中的示例,我(试图)理解对象的属性是基于隐藏类存储的,称为其构造函数“C [N]”。我可能没有正确理解它......例如:

// Let's suppose Object has these hidden classes already

/* Object[[HiddenClasses]] > C0, C1, C2
 *
 * C0 - for "x", goto C1
 * C1 - "x"; for "y", goto C2
 * C2 - "x", "y";
 */

var obj = {
    x: 0
};
// Currently based in C1 to get/put properties

obj.y = 0;
// Now based in C2

1。如果这个新对象添加了一个新属性会发生什么?

obj.z = 0

它的行为是否仍然像Object的第一个实例?

2。如果同一构造函数的对象以隐藏类的相反顺序添加属性会发生什么?

({ y: 5; }); // Will this be based in C2?

3。删除属性会发生什么?它的值是否仅在内存中更改以表示deleted

4。当编译器无法看到其计算属性访问的对象或名称时,是否在隐藏类中完成查找?即:

({ [Math.random()]: 0 }),
randomlyReceivedObject.property;

1 个答案:

答案 0 :(得分:2)

  1. obj.z = 0之后,C2获得了新的转化for "z", goto C3,并为该对象创建了新的隐藏类C3 - "x", "y", "z"

  2. 该对象将有一个新的隐藏类C4 - "y"C0获得了新的转换:for "y", goto C4。如果该对象稍后获得“x”属性,则会创建一个新的隐藏类C5 - "y", "x",并在C4for "x", goto C5中进行转换。 C5C2将永远保持不同。这实际上是由JavaScript规范强制执行的,因为例如一个for..in循环 Object.getOwnPropertyKeys必须按创建顺序迭代属性,V8通过隐藏类跟踪属性创建顺序。 由于拥有更多隐藏类自然会产生速度和内存成本,因此通常建议始终以相同的顺序创建属性(例如,通过使用构造函数)。

  3. 删除属性后,对象将进入字典模式,并且不再使用隐藏类来跟踪其属性。在内部,这是通过一个特殊的隐藏类实现的:C6 - all properties are in the properties dictionary。然后,每个后续属性访问都需要字典查找。如果要避免这种情况,可以手动覆盖属性而不是删除它们:obj.x = null或类似的。 (精细打印:从最近的V8版本开始,有一个例外,如果 last 属性被删除,那么最后隐藏的类转换将被回滚。此实现细节可能会也可能不会将来坚持下去,所以不要依赖它。)

  4. 隐藏类始终用于查找。内联缓存只是缓存这些查找的结果;这总是在执行时发生,而不是在编译时发生。 “编译器”通常不能“看到”对象,因为在编译时还没有对象。