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

How does V8 inline caching work with delete and computed property access?

https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access 中的示例,我(试图)理解对象的属性存储在其构造函数的隐藏 class 中,称之为 "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。如果同一构造函数的对象以与隐藏 classes 相反的顺序添加属性,会发生什么情况?

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

3。如果删除 属性 会怎样?它的值是否仅在内存中更改以表示 deleted?

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

({ [Math.random()]: 0 }),
randomlyReceivedObject.property;
  1. obj.z = 0之后,C2得到一个新的转换for "z", goto C3,并为classC3 - "x", "y", "z"创建一个新的隐藏对象.

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

  3. 当一个属性被删除时,对象被置于字典模式,隐藏的classes不再被用来跟踪它的属性。在内部这是通过一个特殊的隐藏 class: C6 - all properties are in the properties dictionary 实现的。随后的每个 属性 访问都需要进行字典查找。如果你想避免这种情况,你可以手动覆盖属性而不是删除它们:obj.x = null 或类似的。 (细则:在最近的 V8 版本中,有一个例外,如果 last 属性 被删除,那么最后一个隐藏的 class 转换已回滚。此实现细节将来可能会保留,也可能不会保留,所以不要依赖它。)

  4. 隐藏的 classes 总是用于查找。内联缓存只是缓存这些查找的结果;这总是发生在执行时,而不是编译时。 "The compiler"一般不能"see"对象,因为在编译时还没有对象。