使用 Spidermonkey 24、38、45
Spidermonkey documentation说:“堆上的 GC 事物指针必须包装在 JS::Heap 中。唯一的异常(exception)是如果它们作为根添加到 JS_AddRoot() 函数或 JS::PersistentRooted 类中,但是不要'除非确实有必要,否则不要这样做。JS::Heap 指针也必须继续以正常方式进行跟踪,这里不做介绍。”
在这种情况下,跟踪到底意味着什么?以下代码是否遗漏了什么?
struct Foo
{
Foo(JS::HandleObject bar) : _bar(bar) {} // Does that root bar?
~Foo() {_bar = nullptr;} // Does that release memory?
JS::Heap<JSObject*> _bar;
};
Foo *create(JSContext *jscontext, JSObject *parent)
{
JS::RootedObject bar(jscontext, JS_NewObject(jscontext, &SOME_CLASS, NULL, parent));
return new Foo(bar);
}
我需要添加“跟踪”吗?当 bar 对象存储在 Foo 中时,我是否需要 root 对象?我是否应该使用 JS_AddRoot() 函数而不是使用堆来生成根栏?
最佳答案
JS::Heap<T>
用于驻留在堆上的数据结构。跟踪确实是一个要求。没有它,GC 可能会确定您的对象无法访问或重新定位它而不更新您的 JS::Heap<T>
处理。
在 spidermonkey 中追踪对象很简单。您需要使用 JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data)
请求额外的 GC root tracer . JSTraceDataOp 是一个带有接口(interface) void traceOp(JSTracer* trc, void* data)
的函数指针.在您的函数中,您必须调用各种 JS_Call<T>Tracer
(在 Tracer.h 中定义)传递跟踪器和您的对象的方法。此外,您应该调用 JS_TraceChildren
必要时。
使用您的示例,添加跟踪器可能如下所示。
Foo* ref = create(cx, nullptr);
void trace_foos(JSTracer* tracer, void* data) {
JS_CallHeapObjectTracer(tracer, &(ref->_bar), "foo");
}
JS_AddExtraGCRootsTracer(rt, trace_foos, nullptr);
每当 GC 运行时,您的跟踪回调就会运行,您应该遍历对象图并随时跟踪 GC 事情。
关于您评论中的问题-
Foo(JS::HandleObject bar) : _bar(bar) {} // Does that root bar?
bar
已经通过 JS::RootedObject
在堆栈上 Root 酒吧 Foo* create
. Heap<T>
句柄不是根 - 这就是必须追踪它们的原因。一旦create
返回时,对象不再有根。
~Foo() {_bar = nullptr;} // Does that release memory?
没有。 _bar
只是 JS::Heap<T>
的一个实例处理。它指向的东西将在后续循环中被垃圾收集。
关于javascript - 如何在 Spidermonkey 中创建、处理和销毁 JS::Heap<T> 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27393732/