what is wrong with using JS::PersistentRooted

I want to create objects on the heap what but rootedobject causes core dump with the GC 
0
msami
9/10/2019 3:00:42 PM
mozilla.dev.tech.js-engine 2040 articles. 0 followers. Post Follow

2 Replies
3 Views

Similar Articles

[PageSpeed] 10

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.


0
Steve
9/10/2019 5:23:21 PM
>=20
> That is the general idea, and I know it is complicated and confusing.=20
> You'll need to post more details of what you're running into if you need=
=20
> more than that.

thanks for your reply, my application is Vxml Interpreter for voice-platfor=
m that services calls, each call go throw vxml document which uses spidermo=
nkey to interpret javascripts, the problem is these calls are dynamically a=
llocated, I needd to create a wrapper for JSAPI that lives with the call an=
d get destroyed with it=20

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

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=20

the big problem is that we need to use JS::AutoObjectVector and it causes t=
he 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
msami
9/11/2019 8:55:56 AM
Reply: