Proper rooting for strings returned from property get?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Proper rooting for strings returned from property get?

Alex Rickabaugh
Hi all, question about garbage collection and JSString objects:

I am using SpiderMonkey to expose some C structure members (mostly
char* strings) to a JS scripting engine. As the data values of these C
structures may change often, I have their equivalent properties in my
JSClass definitions flagged as JSPROP_SHARED, which according to
documentation tells SpiderMonkey not to use a stored value slot for
the property, and call my accessor each time to get it.

My question relates to my accessor's behavior. I set the return jsval
to something like:

*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(context, cstruct->charptr));

Will this work? It would be completely impractical (and a waste of
space) to keep rooted JSString copies of all C strings in my program,
so the behavior I want is for the JSString to be created by my
accessor when the property is accessed, and garbage collected soon
after once the code has done what it needs with it, assuming it's not
linked to some rooted object.

The code case I'm concerned about is something like this:

function foo()
{
   // Get property as a local-scope variable
   var str = bar.property;
   // Execute a function call so we branch and garbage collector runs.
   baz();
   // Attempt to access 'str'.
   alert("str is: " + str);
}

Will this indeed work, or is there a chance that my JSString
(referenced by 'str') will be GC'd before it is used?

function foo()
{
    var str = "string 1 " + "string 2!";
    baz();
    alert("str is: " + str);
}

For this to work, the JSString created to hold the result of the
constant string concatenation would have to be rooted in the local
scope (probably as a result of JS_EnterLocalRootScope() being called).
Thus, it would be safe from GC until the function execution ended, at
which point if it wasn't rooted elsewhere, it would be eligible for
GC.

I would think, if during the execution of a function, the JS engine
enters a local root scope, then any objects created (or at least
returned) by my property get operation would be protected in that
local root scope.

I'm wondering if this is indeed true, or do I need to have my property
get operation enter its own local root scope, and
JS_LeaveLocalRootScopeWithResult() with my string, to ensure its
guaranteed survival until it's no longer needed.

Thanks for taking the time to read this and help me out!

--Alex
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Proper rooting for strings returned from property get?

Wes Garland
Hi, Alex!

I think you're way over-thinking this... pretty common
jsapi-noob-but-competent-coder mental bug if you ask me. :)

I'm stretching my memory a bit -- haven't really done jsapi work in a year
-- but the general solution you want here is to create accessor functions
("getters" and "setters") for your properties which return a JSString to
spidermonkey through the vp C function parameter.   The key realization here
is that vpl is *already a GC root*.  That is guaranteed by the API. So this
statement of yours does does not have any GC hazards:

*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(context, cstruct->charptr));

..STRING_TO_JSVAL is just a casting macro, so it doesn't create any GC-able
objects as side effects, and as soon as the assignment is made, you're safe.

I forget the details behind JSPROP_SHARED, but It sounds like you're using
that properly.

The code case you're worrying about is not an issue.  Once you assigned your
JSString to *vp, it is safe as long as that JS variable is in JS scope.

If you're worried about local root scopes, etc, my suggestion is: try REALLY
hard to avoid using it, because except for a few esoteric cases, it's
un-needed and has a few traps. Using a root-as-you-go strategy (assigning to
*argv[n], *rval, *vp) you can also eliminate the need for JS_SetNamedRoot()
calls as well.

Wes
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Proper rooting for strings returned from property get?

Jason Orendorff-2
In reply to this post by Alex Rickabaugh
On 1/13/09 7:40 PM, alx wrote:
> Hi all, question about garbage collection and JSString objects:
> [...]
>
> *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(context, cstruct->charptr));
>
> Will this work?

Yes, that's fine.  Wes's response is 100% right but I want to add a link:

https://developer.mozilla.org/en/SpiderMonkey/JSAPI_User_Guide#Garbage_collection

-j
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Proper rooting for strings returned from property get?

Alex Rickabaugh
On Jan 16, 12:40 pm, Jason Orendorff <[hidden email]> wrote:

> On 1/13/09 7:40 PM, alx wrote:
>
> > Hi all, question about garbage collection and JSString objects:
> > [...]
>
> > *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(context, cstruct->charptr));
>
> > Will this work?
>
> Yes, that's fine.  Wes's response is 100% right but I want to add a link:
>
> https://developer.mozilla.org/en/SpiderMonkey/JSAPI_User_Guide#Garbag...
>
> -j

Okay, that makes sense, thanks!

Wes: I will take your advice and avoid using local root scopes (can't
see a situation where I'd need them anyhow as long as *vp is
automatically rooted).
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine