Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

what is wrong with using JS::PersistentRooted

44 views
Skip to first unread message

msami

unread,
Sep 10, 2019, 11:00:44 AM9/10/19
to
I want to create objects on the heap what but rootedobject causes core dump with the GC

Steve Fink

unread,
Sep 10, 2019, 1:23:37 PM9/10/19
to msami, dev-tech-...@lists.mozilla.org
On 9/10/19 8:00 AM, msami wrote:
> I want to create objects on the heap what but rootedobject causes core dump with the GC

I'm not clear on what your question is.

JS::PersistentRooted should normally only be used for true roots (stuff
that should be alive no matter what.) The main problem with using it is
that it makes it much too easy to create leaks -- you put a
PersistentRooted in an object that is destroyed in a finalizer, but
there ends up being a path from that object back to itself. This is
really, really easy to do. The other issue with PersistentRooteds is
that you have to clear them out before shutting down or it will assert
that it's shutting down with stuff still alive. (You might have some
important finalizers to run, but there's no way to know what order to
run them in, so this is a coding error.)

I'm guessing, though, that you have something like

    struct MyObject {

        Rooted<JSObject*> obj;

        ...

    }

and you're allocating a MyObject instance on the heap? That *should*
core dump. In a DEBUG build, it will assert. Please develop with a DEBUG
build; it's basically impossible to use the JSAPI correctly otherwise.
(And then please *don't* use a DEBUG build when looking at performance,
because they're horribly slow.)

It crashes because Rooted cannot be used on the heap. It is a stack-only
class. The above should probably be Heap<JSObject*> if it is part of an
object graph (most likely), or PersistentRooted<JSObject*> if it really
is a true root (much less likely). If it is Heap<JSObject*>, then you
additionally need to trace it at the appropriate time. The recommended
way to do that is to implement a method `void trace(JSTracer*)` that
calls `JS::TraceEdge(trc, &obj, "my obj")`, and then call it at the
right time. (The reason to use that exact trace() signature is that it
allows using Rooted<MyObject*> on the stack. If you don't care about
that, then you don't need to make the separate method; just call
JS::TraceEdge at the right time.)

The right time will be during a GC. You'll need to get a callback
somehow so your C++ code knows when to trace stuff.
JS_AddExtraGCRootsTracer is one such way; the callback will be given the
JSTracer* to use. Or you can use a PersistentRooted<SomeOtherObject*>
which will call `void SomeOtherObject::trace(JSTracer*)` when needed for
a GC.

That is the general idea, and I know it is complicated and confusing.
You'll need to post more details of what you're running into if you need
more than that.


msami

unread,
Sep 11, 2019, 4:55:57 AM9/11/19
to
>
> That is the general idea, and I know it is complicated and confusing.
> You'll need to post more details of what you're running into if you need
> more than that.

thanks for your reply, my application is Vxml Interpreter for voice-platform that services calls, each call go throw vxml document which uses spidermonkey to interpret javascripts, the problem is these calls are dynamically allocated, I needd to create a wrapper for JSAPI that lives with the call and get destroyed with it

the model we use now we init the JSAPI on a layer higher than the calls serving level, all calls are on the same thread on cx on runtime

each call has it's a global object when we use rootedobject it causes core dump so we replaced it with persistentRooted and it seems to work fine

the big problem is that we need to use JS::AutoObjectVector and it causes the same problem as rootedObject when GC start Running


we use JS::AutoObjectVector as scope chain to evaluate on it as the vxml is multilayered each layer can see upper layers and not vise verse
0 new messages