v8引擎中的hidden 类是如何实现的?
How are hidden classes in the V8 engine implemented?
因此,我在 public Wiki 上广泛阅读了 V8
引擎,并且了解了隐藏的 类 如何查找属性的概念。 v8 design elements
然而,我真正不明白的是这比散列更快 table。
根据这个,它说属性存储在不同的偏移量中,但是对于每个偏移量,您必须检查它是否正确 属性。这是否意味着在最坏的情况下,您必须遍历所有属性才能获得所需 属性 的正确偏移量?
由于 hashtables 是恒定时间查找,它们通常不会比这更快吗?
您的问题似乎是通过 here, here, and here 的某种组合得到解答的。
简而言之,根据我对这些链接的理解:
哈希表比恒定时间查找慢,因此 V8 尽可能使用后者,但如果对象变得太复杂而无法使用隐藏 classes 很好地处理,则回退到前者。
线性扫描显然也不好,但在我看来,V8 试图优化 代码 以通过一种称为 内联缓存:当您的代码尝试重复访问 obj.prop
时,V8 最终决定只动态修补生成的代码,以便 属性 访问成为常量时间查找给定的偏移量。
当然,如果预期的 class 类型是错误的,那么它必须回退并尝试慢速查找。
function CompileNamedLoadFastProperty(klass, key)
在 this page 上试图解释:
function CompileNamedLoadFastProperty(klass, key) {
// Key is known to be constant (named load). Specialize index.
var index = klass.getIndex(key);
function KeyedLoadFastProperty(t, k, ic) {
if (t.klass !== klass) {
// Expected klass does not match. Can't use cached index.
// Fall through to the runtime system.
return NAMED_LOAD_MISS(t, k, ic);
}
return t.properties[index]; // Veni. Vidi. Vici.
}
return KeyedLoadFastProperty;
}
function NAMED_LOAD_MISS(t, k, ic) {
var v = LOAD(t, k);
if (t.klass.kind === "fast") {
// Create a load stub that is specialized for a fixed class and key k and
// loads property from a fixed offset.
var stub = CompileNamedLoadFastProperty(t.klass, k);
PatchIC("LOAD", ic, stub);
}
return v;
}
因此,我在 public Wiki 上广泛阅读了 V8
引擎,并且了解了隐藏的 类 如何查找属性的概念。 v8 design elements
然而,我真正不明白的是这比散列更快 table。
根据这个,它说属性存储在不同的偏移量中,但是对于每个偏移量,您必须检查它是否正确 属性。这是否意味着在最坏的情况下,您必须遍历所有属性才能获得所需 属性 的正确偏移量?
由于 hashtables 是恒定时间查找,它们通常不会比这更快吗?
您的问题似乎是通过 here, here, and here 的某种组合得到解答的。
简而言之,根据我对这些链接的理解:
哈希表比恒定时间查找慢,因此 V8 尽可能使用后者,但如果对象变得太复杂而无法使用隐藏 classes 很好地处理,则回退到前者。
线性扫描显然也不好,但在我看来,V8 试图优化 代码 以通过一种称为 内联缓存:当您的代码尝试重复访问 obj.prop
时,V8 最终决定只动态修补生成的代码,以便 属性 访问成为常量时间查找给定的偏移量。
当然,如果预期的 class 类型是错误的,那么它必须回退并尝试慢速查找。
function CompileNamedLoadFastProperty(klass, key)
在 this page 上试图解释:
function CompileNamedLoadFastProperty(klass, key) {
// Key is known to be constant (named load). Specialize index.
var index = klass.getIndex(key);
function KeyedLoadFastProperty(t, k, ic) {
if (t.klass !== klass) {
// Expected klass does not match. Can't use cached index.
// Fall through to the runtime system.
return NAMED_LOAD_MISS(t, k, ic);
}
return t.properties[index]; // Veni. Vidi. Vici.
}
return KeyedLoadFastProperty;
}
function NAMED_LOAD_MISS(t, k, ic) {
var v = LOAD(t, k);
if (t.klass.kind === "fast") {
// Create a load stub that is specialized for a fixed class and key k and
// loads property from a fixed offset.
var stub = CompileNamedLoadFastProperty(t.klass, k);
PatchIC("LOAD", ic, stub);
}
return v;
}