javascript - V8 中动态对象访问如何工作?

标签 javascript v8

我惊讶地发现 JavaScript 对象 are not in fact hash maps under the hood, instead they are more similar to structs 。据我了解,获取和设置对象的属性很快,因为值的内存位置位于固定偏移处,就像在结构或类中一样。我不明白的是语法如何映射到该固定偏移量。即当编译器看到 obj.aobj['a'] 时会发生什么。该语法是否在运行时、编译时或 JIT 时转换为整数偏移量?我想我想要理解的是它如何有效地将传入的字符串“a”转换为整数索引,而不需要执行类似 index = hash('a') % objectLength 的操作。

也许我的知识差距是我没有完全了解结构在编译器级别的工作原理。

最佳答案

(这里是 V8 开发人员。)

JavaScript objects are not in fact hash maps under the hood, instead they are more similar to structs.

根据记录,Bergi 正确地指出,这在一个引擎中是正确的,即使在该引擎中也并非总是如此。 JavaScript 引擎在如何准确地在内部表示对象方面有很大的自由度,并且它们确实利用了这种自由度。

What I don’t understand is how the syntax maps to that fixed offset. Ie what happens when the compiler sees obj.a or obj[‘a’]. Is that syntax transformed into an integer offset at run time or compile time or JIT?

该系统基于缓存和“隐藏类”(有时称为“对象形状”或“[对象]形状描述符”)。

当你有一个对象obj = {a: 42, b: "hello", c: null}时,它将有一个隐藏类(我们称之为hiddenClassA) > 列出所有属性及其偏移量,例如“属性 a 存储在偏移量 12 处”。

第一次执行包含像 obj.a 这样的属性加载的函数时将使用未优化的代码。此代码必须检查对象,在其隐藏类的属性列表中找到a,从那里检索正确的偏移量,然后从对象中的该偏移量读取以获取属性的值。然后,该对(隐藏类、偏移量)会针对此特定属性加载进行缓存,因此,如果下次出现另一个具有相同隐藏类的对象,则下一次查找(即使在尚未优化的代码中)也会运行得更快。

如果函数运行得足够热,它最终会得到优化。优化编译器查看未优化代码已缓存的隐藏类和偏移量,并假设应用程序的 future 行为将与过去的行为一样,因此它将发出如下代码序列:

  1. 验证obj具有隐藏类hiddenClassA,否则进行反优化
  2. 从偏移量 12 加载

其中“deoptimize”意味着该函数的整个优化代码将不得不被丢弃,因为它显然基于无效的假设,并且执行将返回到未优化的代码以收集更多类型反馈(直到稍后可能出现)如果仍然运行得足够热,则使用新反馈重新优化)。只要它不需要去优化,优化后的代码将几乎与 C 对结构所做的一样快,并且它不需要进行任何属性查找,因为它只依赖于关于缓存的偏移量。

这种机制也是为什么立即编译优化代码没有意义的原因:当优化编译器没有可用的缓存类型信息(由未优化的执行生成)时,诸如属性访问之类的事情就无法合理地优化。因为这样优化编译器会问你同样的问题:“我到底应该如何找出偏移属性 a 映射到什么???”

关于javascript - V8 中动态对象访问如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65946571/

相关文章:

javascript - 使用 Javascript 更改 CSS 中定义的 SVG 图像的颜色

javascript - iOS 混合应用程序 - Google map API 错误 : RefererNotAllowedMapError

javascript - AngularJS依赖注入(inject)的顺序

javascript - Chartjs 和 Polymer 1.7.0

javascript - 在 React Hooks 中使用具有 `Set` 状态的动态变量?

node.js - 如何反编译Bytenode "jsc"文件?

javascript - 从源代码构建 V8

javascript - Javascript Maps 是否有一定数量的可以设置的键,或者它们是否有一定数量的可以完成的键操作?

javascript - JavaScript ES6 (<<) 中的按位左移是否在 63 位以上循环?

c++ - 将 v8::Local<v8::Object> 存储在类静态 ​​std::vector 中