Skip to content Skip to sidebar Skip to footer

How To Create, Handle, And Destroy Js::heap Objects In Spidermonkey?

Using Spidermonkey 24, 38, 45 Spidermonkey documentation says: 'GC thing pointers on the heap must be wrapped in a JS::Heap. The only exception to this is if they are added as root

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?"