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

Question about 'root as you go' GC Tip

22 views
Skip to first unread message

Dave Wolfe (Skew Matrix)

unread,
Jul 28, 2008, 4:10:27 PM7/28/08
to
A project I'm working on recently ran into a garbage collection crash
that caused us to get super paranoid about how we're retrieving values
from JavaScript. It's a multithreaded (JS_THREADSAFE) app, so we want
to be sure we're doing everything possible to avoid races/deadlocks/
etc.

We're pretty sure the crash turned out to be because of this bug:

- https://bugzilla.mozilla.org/show_bug.cgi?id=438633

We've found a workaround for it, but we've since been having some
internal debates about whether code like the following is okay w.r.t.
garbage collection:

// Note: The calling code has already called JS_BeginRequest() on
'cx',
// so we don't bother doing it again here...
JSBool setFileName(JSContext* cx,
JSObject*, uintN argc,
jsval* argv,
jsval*)
{

if (argc != 2 ||
!JSVAL_IS_STRING(argv[0]) ||
!JSVAL_IS_STRING(argv[1]) )
{
emitError(...);
return JS_FALSE;
}

std::string streamName =
JS_GetStringBytes(JSVAL_TO_STRING(argv[0]) );
std::string fileName = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]) );

...
}

Specifically, the question is, can 'streamName' or 'fileName' ever get
garbage values? Or can the app *crash* because we didn't root the
temporaries?

It has been suggested that it would be safer to rewrite the above two
assignments as:

JSString* strStreamName = JS_ValueToString(cx, argv[0]);
if (!strStreamName) { emitError(...); return JS_FALSE; }
argv[0] = STRING_TO_JSVAL(strStreamName);

JSString* strFileName = JS_ValueToString(cx, argv[1]);
if (!strFileName) { emitError(...); return JS_FALSE; }
argv[1] = STRING_TO_JSVAL(strFileName);

std::string streamName = JS_GetStringBytes(strStreamName);
std::string fileName = JS_GetStringBytes(strFileName);


I suspect that the extra six lines are simply a waste of space in this
case, but I've been wrong about JSAPI questions like this often enough
that I no longer trust my own judgement. Is it okay to just say:

std::string streamName =
JS_GetStringBytes(JSVAL_TO_STRING(argv[0]) );
std::string fileName = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]) );

and be done with it?

Any insight much appreciated...

Mike Shaver

unread,
Jul 31, 2008, 9:40:18 AM7/31/08
to Dave Wolfe (Skew Matrix), dev-tech-...@lists.mozilla.org
On Mon, Jul 28, 2008 at 1:10 PM, Dave Wolfe (Skew Matrix)
<dwolf...@hotmail.com> wrote:
> Is it okay to just say:
>
> std::string streamName =
> JS_GetStringBytes(JSVAL_TO_STRING(argv[0]) );
> std::string fileName = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]) );
>
> and be done with it?

Yes; anything on the JS stack is safe from collection.

Mike

0 new messages