How To Create, Handle, And Destroy Js::heap Objects In Spidermonkey?
Solution 1:
JS::Heap<T>
are used in data structures which reside on the heap. Tracing is indeed a requirement. Without it, the GC may either determine your object is unreachable or relocate it without updating your JS::Heap<T>
handle.
Tracing objects in spidermonkey is simple. You need to request an extra GC root tracer using JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data)
. The JSTraceDataOp is a function pointer with the interface void traceOp(JSTracer* trc, void* data)
. In your function, you must call the various JS_Call<T>Tracer
(defined in Tracer.h) methods passing the tracer and your object. Additionally, you should call JS_TraceChildren
as necessary.
Using your example, adding a tracer might look something like the following.
Foo* ref = create(cx, nullptr);
voidtrace_foos(JSTracer* tracer, void* data){
JS_CallHeapObjectTracer(tracer, &(ref->_bar), "foo");
}
JS_AddExtraGCRootsTracer(rt, trace_foos, nullptr);
Whenever GC runs, your trace callback will run and you should traverse your object graph and trace GC things as you go.
As for the questions in your comments -
Foo(JS::HandleObject bar) : _bar(bar) {} // Does that root bar?
bar
is already rooted on the stack by the JS::RootedObject
bar in Foo* create
. Heap<T>
handles are not roots - this is why they must be traced. As soon as create
returns, the object is no longer rooted.
~Foo() {_bar = nullptr;} // Does that release memory?
No. _bar
is just an instance of the JS::Heap<T>
handle. The thing it points to will be garbage collected on a subsequent cycle.
Solution 2:
Based on jwilm's answer here is an example of a Foo class implementation.
void trace_obj(JSTracer* tracer, void* data)
{
JS_CallObjectTracer(tracer, (JS::Heap<JSObject*>*)data, "jsobj");
}
class Foo
{
public:
Foo(JSRuntime *rt, JS::HandleObject bar)
: _rt(rt),
_bar(bar)
{
if (_bar.get())
JS_AddExtraGCRootsTracer(_rt, trace_obj, &_bar);
}
Foo(Foo const &f)
: _rt(f._rt),
_bar(f._bar)
{
if (_bar.get())
JS_AddExtraGCRootsTracer(_rt, trace_obj, &_bar);
}
~Foo()
{
if (_bar.get())
JS_RemoveExtraGCRootsTracer(_rt, trace_obj, &_bar);
}
private:
JSRuntime *_rt;
JS::Heap<JSObject*> _bar;
};
Post a Comment for "How To Create, Handle, And Destroy Js::heap Objects In Spidermonkey?"