Re: How do I trace objects on the heap with JS 59
Miles <[email protected]> Thu, 16 Aug 2018 07:33:40 -0700 (PDT)
| Newsgroups | gmane.comp.mozilla.devel.jseng |
|---|---|
| Message-ID | <[email protected]> |
Please can I clarify how tracing interacts with garbage collection?
Hi, thanks for all the help and patience so far but I'm struggling with this somewhat as I don't really understand how tracing works. There is very little information on it in the JSAPI reference. I would be really grateful if someone could give some more clarification so I can try to understand how to use it properly.
In my embedding that currently uses JS 1.8.5 I have some classes defined using JSClass (e.g. I have Widget, WidgetItem and Window classes). Each of these has a constructor and this stores a structure in the private data field of the object using JS_SetPrivate. I define a JSfinalizeOp for the class where I then return the structure for this memory.
In my embedding this structure stores the pointer back to the JSObject. For example the structure I store for my 'Widget' class looks something like
typedef struct db_js_widget_struct {
JSObject *jsobject; /* The Widget object in javascript */
JSContext *context; /* The context in javascript */
int id; /* The id of the widget */
int type; /* The type of widget */
int bg_col; /* The background colour */
...
} DB_JS_WIDGET;
This enables me to get back to the object.
When using JS 1.8.5 normally when the object goes out of scope the finalizeOp will be called when GC is done and my structure will be returned.
However, in some special cases I wanted to ensure that the object was not garbage collected so I rooted the object using JS_AddObjectRoot.
When I had finished with the object I could then call JS_RemoveObjectRoot and then when GC was done the object would not be rooted anymore and would be freed.
So I had two different use cases. The 'normal' case where I wanted the object to be garbage collected when it went out of scope and the 'special' case where I wanted to protect the object from being garbage collected by rooting. However in both cases I wanted to store the (JSObject *) pointer.
Now moving to JS 59 from my understanding I cannot store the (JSObject *) pointer directly on the structure as GC is now done with a moving GC so (JSObject *) pointers can 'move'. Correct?
So I have two options.
1. use JS::PersistentRootedObject
2. use JS::Heap<JSObject *> and trace it.
If I use JS::PersistentRootedObject then I think that my object will *always* be rooted so will *never* go 'out of scope' and be garbage collected. i.e. I cannot use this for my 'normal' use case.
So I think I have to use JS::Heap<JSObject *> and trace it.
My structure now becomes
typedef struct db_js_widget_struct {
JS::Heap<JSObject *> jsobject; /* The Widget object in javascript */
JSContext *context; /* The context in javascript */
int id; /* The id of the widget */
int type; /* The type of widget */
int bg_col; /* The background colour */
...
} DB_JS_WIDGET;
and on my JSClass I now define a traceOp which looks something like
static void dj_widget_trace(JSTracer *trc, JSObject *obj)
/* ===========================
*
* Tracing for JS::Heap<T> GC things for Widget
*/
{
DB_JS_WIDGET *js_widget;
/* Get the private data for the widget and return it. */
js_widget = (DB_JS_WIDGET *) JS_GetPrivate(obj);
JS::TraceEdge(trc, &js_widget->jsobject, "widget");
}
This is where I don't understand the process.
What does calling JS::TraceEdge do? Does it
1. Ensure that jsobject is kept up to date to refer to the correct (JSObject *) pointer
or
2. Root the object to stop GC on it.
Or perhaps it is both?
Basically, how can I do my two 'normal' and 'special' use cases using tracing? Can I somehow store the JSObject pointer in a structure but still allow it to go out of scope as normal for my 'normal' case and also prevent GC in some circumstances for my 'special' case. Is it possible?
I *think* this is the same question that James is asking...
I hope this makes sense. Apologies if I haven't explained it clearly.
Many thanks in advance for any information someone might be able to give.
Miles