Implement GC-safety checks for spidermonkey

RESOLVED FIXED

Status

()

Core
Rewriting and Analysis
RESOLVED FIXED
10 years ago
2 years ago

People

(Reporter: (dormant account), Unassigned)

Tracking

(Blocks: 1 bug)

Trunk
x86
Mac OS X
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

10 years ago
This is still applicable for 1.9. Should investigate if this is easy to do with either gcc dehydra(ideal) or the new typedef stuff in pork.

http://wiki.mozilla.org/GC_SafetySpec
(Reporter)

Comment 1

10 years ago
Igor,
I'm trying to start on my analysis and I already ran into a case I'm not too sure about.

In JS_CallFunctionName in jsapi.c, what rule am I supposed to follow for jsval fval;
Status: NEW → ASSIGNED

Comment 2

10 years ago
(In reply to comment #1)
> Igor,
> I'm trying to start on my analysis and I already ran into a case I'm not too
> sure about.
> 
> In JS_CallFunctionName in jsapi.c, what rule am I supposed to follow for jsval
> fval;

The code relies on the fact that js_InternalCall stores a copy of fval into a rooted location before calling anything that trigger GC. It is well known how fragile is that so you can treat it as a bug.
(Reporter)

Updated

9 years ago
Blocks: 430328
(Reporter)

Comment 3

9 years ago
Note to self, JS_PUSH_SINGLE_TEMP_ROOT is a value of rooted rooting...So I think the rule should say that one can not dereference anything below the value of the root

So if jsval is rooted..then turning that into jsval* is forbidden, if jsval* is rooted, then doing jsval** is forbidden..etc.
(Reporter)

Comment 4

9 years ago
Above is not quite correct

Code:
JSTempValueRooter tvr;
jsval v;
JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr)

Result:
tvr is rooted
v is copy-of-rooted

&v a violation
&tvr.u.value is safe
(Reporter)

Comment 5

9 years ago
functions marked with JS_PUBLIC_API are unsafe, thus parameters should be rooted

Comment 6

9 years ago
(In reply to comment #4)
> Above is not quite correct
> 
> Code:
> JSTempValueRooter tvr;
> jsval v;
> JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr)
> 
> Result:
> tvr is rooted
> v is copy-of-rooted

Note this code is bogus: jsval is not initialized! What happens with public API is the following code pattern:

void public_api(..., jsval v)
{
    JSTempValueRooter tvr;
    JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr)
    ....

}

Here according to the generic rule v is already copy-of-rooted. So taking its address is prohibited. I guess the only thing this example shows that the jsval argument to JS_PUSH_SINGLE_TEMP_ROOT must be a rooted or copy-of-rooted jsval. But this is just a generic rule for any function call.    
(Reporter)

Comment 7

9 years ago
To clarify comment 6, v becomes copy-of-rooted IFF JS_PUBLIC_API...In all other cases the value argument to JS_PUSH* should be copy-of-rooted or a constant
(Reporter)

Updated

9 years ago
Depends on: 432507
(Reporter)

Comment 8

9 years ago
Lefty rule: No part of a struct is ever registered(such that we dont need to do shape analysis), so when checking for rootedness of a.nested.member, only the leftmost part needs to be checked for rootedness.
(Reporter)

Updated

9 years ago
Depends on: 432546
(Reporter)

Comment 9

9 years ago
in order to allow outparams

foo(&tvr.u.value) we must assume that no parameters ever escape the stack...if they do they shall be annotated as ESCAPES
(Reporter)

Comment 10

9 years ago
So turns out, we don't just manage jsvals, but all other parameters entering js functions.

* One can not pass part of a struct to a function, unless it is explicitly registered.
* Currently only jsvals have a way to get registered. Something will be developed for structs too

* Due to expansion of the spec, we are now aiming for June completion of the analysis.
(Reporter)

Comment 11

8 years ago
So last time I tried this I had to give up because inferring rootedness turned to be too painful due to jsvals found in structs, etc.

I think the only realistic approach is to mark the code explicitly.

A template wrapper might be ok so it's enforced at the language level. If that's too ugly we can use a typedef(but that involves making new typedefs for jsval, JSObject, etc).


Basically I want easy to spot transitions like:
JSRooted<jsval> foo = make_rooted(v);
Now foo is easy to track and it's easy to tell that v is not rooted. This becomes especially useful for struct members, as without annotation it's really hard to determine when things are rooted in there(due to transitive rooting).

Is this kind of API-change acceptable? I think we'd have to go with typedefs to stay compatible with existing spidermonkey API.
Explicit template type is fine. We need to vouch that a pointer (usually a parameter, sometimes an intentional weak ref that's safe for a well-inspected critical section, or safe because it's scanned by an owning object, e.g. dslots in JSObject) is already rooted. Otherwise if you are allocating a jsval you probably need to root it.

Igor, any comments?

/be
(Reporter)

Comment 13

8 years ago
(In reply to comment #12)
> Explicit template type is fine. We need to vouch that a pointer (usually a
> parameter, sometimes an intentional weak ref that's safe for a well-inspected
> critical section, or safe because it's scanned by an owning object, e.g. dslots
> in JSObject) is already rooted. Otherwise if you are allocating a jsval you
> probably need to root it.

Actually I'd like to mark parameters too.
Yes, "mark" as in annotate or (if we can use C++) apply the template type -- but this vouches without adding extra rooting. For in parameters the caller must root so this is the manually annotated edge in the transitive closure graph that helps the analysis. It's not automation that causes a redundant root. Right?

/be

Comment 15

8 years ago
(In reply to comment #11)
> Basically I want easy to spot transitions like:
> JSRooted<jsval> foo = make_rooted(v);
> Now foo is easy to track and it's easy to tell that v is not rooted. This
> becomes especially useful for struct members, as without annotation it's really
> hard to determine when things are rooted in there(due to transitive rooting).

Do you mean that JSRooted<> should annotate any rooted thing including structs with jsvals? I suspect that this would be rather invasive. And I am not sure how this would help with structs.
This is a mass change. Every comment has "assigned-to-new" in it.

I didn't look through the bugs, so I'm sorry if I change a bug which shouldn't be changed. But I guess these bugs are just bugs that were once assigned and people forgot to change the Status back when unassigning.
Status: ASSIGNED → NEW
AFAICT, this has now all been implemented using Rooted and Handle types, and in conjunction with the sixgill-based static rooting analysis.
Status: NEW → RESOLVED
Last Resolved: 2 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.