V8需要声明HandleScope才能清除在作用域内创建的任何Local句柄.我知道HandleScope将取消引用这些句柄进行垃圾收集,但我很感兴趣为什么每个Local类都不会像大多数内部ref_ptr类型的助手那样自行解除引用.
我的想法是,HandleScope可以通过一次性转储大量句柄而不是像在ref_ptr类型作用域类中那样逐个转储来更有效地完成它.
以下是我对文档和handles-inl.h源代码的理解.我也可能是完全错误的,因为我不是V8开发人员,文档很少.
垃圾收集器有时会将内容从一个内存位置移动到另一个内存位置,并且在一次扫描期间,还会检查哪些对象仍然可以访问,哪些不可访问.与类似的引用计数类型相比std::shared_ptr,这能够检测和收集循环数据结构.为了实现这一切,V8必须对可以访问的对象有一个很好的了解.
另一方面,在一些计算的内部过程中,对象被创建和删除了很多.您不希望每个此类操作都有太多开销.实现这一目标的方法是创建一堆句柄.在某些C++计算中,该堆栈中列出的每个对象都可以从某个句柄中获得.除此之外,还有持久句柄,这可能需要更多的工作来设置,并且可以在C++计算之后生存.
拥有一堆引用需要您以类似堆栈的方式使用它.该堆栈中没有"无效"标记.堆栈底部到顶部的所有对象都是有效的对象引用.确保这一点的方法是LocalScope.它使事物层次化.使用引用计数指针,您可以执行以下操作:
shared_ptr<Object>* f() {
shared_ptr<Object> a(new Object(1));
shared_ptr<Object>* b = new shared_ptr<Object>(new Object(2));
return b;
}
void g() {
shared_ptr<Object> c = *f();
}
Run Code Online (Sandbox Code Playgroud)
这里首先创建对象1,然后创建对象2,然后函数返回并且对象1被破坏,然后对象2被销毁.这里的关键点是对象1无效但对象2仍然有效的时间点.这就是LocalScope要避免的目标.
其他一些GC实现检查C堆栈并查找它们在那里找到的指针.这很容易出现误报,因为实际上数据的东西可能被误解为指针.对于可达性,这可能看起来相当无害,但是当你移动对象时重写指针,这可能是致命的.它还有许多其他缺点,并且很大程度上依赖于语言的低级实现如何实际工作.V8通过将句柄堆栈与函数调用堆栈分开来避免这种情况,同时确保它们充分对齐以保证所提到的层次结构要求.
提供另一个比较:只有一个引用的对象shared_ptr在其C++块作用域结束后变为可收集(实际上将被收集).v8::Handle当离开包含HandleScope对象的最近的封闭范围时,a引用的对象将变为可收集的.因此,程序员可以更好地控制堆栈操作的粒度.在性能很重要的紧密循环中,HandleScope为整个计算维护一个单独的循环可能很有用,这样您就不必经常访问句柄堆栈数据结构.另一方面,这样做会在计算的整个持续时间内保持所有对象,如果这是一个迭代多个值的循环,那将非常糟糕,因为所有这些都将保持到最后.但是程序员可以完全控制,并且可以以最合适的方式安排事情.
就个人而言,我一定要建一个 HandleScope
一般情况下,我不会HandleScope为每个内部函数创建一个,如果我可以确定调用它的每个其他函数已经设置了一个HandleScope.但那可能是品味问题.
免责声明:这可能不是官方答案,更多的是我个人的想法;但 v8 文档在这个主题上几乎没有用处。所以我可能被证明是错的。
据我了解,在开发各种基于 v8 的支持应用程序时。它是处理 C++ 和 javaScript 环境之间差异的一种方法。
想象一下以下序列,自解引用指针可能会破坏系统。
- JavaScript 调用 C++ 包装的 v8 函数:让我们说 helloWorld()
- C++ 函数创建一个值为“hello world =x”的 v8::handle
- C++ 将值返回给 v8 虚拟机
- C++ 函数执行通常的资源清理工作,包括句柄的取消引用
- 另一个C++函数/进程,覆盖释放的内存空间
- V8 读取句柄:并且数据不再相同“hell!@(#...”
这只是两者之间复杂的矛盾的表面;因此,为了解决将JavaScript VM(虚拟机)连接到C++ 接口代码的各种问题,我相信开发团队决定通过以下方式简化问题......
- 所有变量句柄都将存储在“存储桶”(又名 HandleScopes)中,并在需要时由各自的C++ 代码构建/编译/运行/销毁。
- 此外,所有函数句柄仅引用 C++ 静态函数(我知道这很烦人),这确保了函数调用的“存在”,无论构造函数/析构函数如何。
从开发的角度来看,它标志着 JavaScript VM 开发团队和 C++ 集成团队(Chrome 开发团队?)之间的显着区别。让双方能够互不干扰地工作。
最后,也可能是为了简单起见,模拟多个虚拟机:因为 v8 最初是为 google chrome 设计的。因此,每当我们打开/关闭选项卡时,简单的 HandleScope 创建和销毁都会使 GC 管理变得更加容易,特别是在运行多个 VM 的情况下(chrome 中的每个选项卡)。
| 归档时间: |
|
| 查看次数: |
3085 次 |
| 最近记录: |