Confirmed users
328
edits
(Created page with "= SpiderMonkey Garbage Collector Handle API = == Background == Some background: the fundamental issue at hand is that SpiderMonkey uses garbage collection, which is a way of re...") |
|||
| Line 15: | Line 15: | ||
Consider what happens to obj1 if a garbage collection is triggered by the JS_NewObject() call for obj2. Nothing currently points to (refers to) obj1 other than the local variable 'obj1' itself. Without any other code or mechanism in place, the GC will delete obj1 and the JS_DefineProperty() will crash. | Consider what happens to obj1 if a garbage collection is triggered by the JS_NewObject() call for obj2. Nothing currently points to (refers to) obj1 other than the local variable 'obj1' itself. Without any other code or mechanism in place, the GC will delete obj1 and the JS_DefineProperty() will crash. | ||
Currently, SpiderMonkey handles this problem with a conservative stack scanner. During a GC, it scans the C++ stack to find anything that looks like a pointer to a GC-able object, and treats anything it finds as being in use. It may find some things that are no longer in use or that only look like a pointer to a GC-able thing (gcthing). In that case, it erroneously mark them as in use, as well as anything they point to, resulting in some garbage not getting collected. This is generally a short-term problem, however. | Currently, SpiderMonkey handles this problem with a conservative stack scanner. During a GC, it scans the C++ stack to find anything that looks like a pointer to a GC-able object ("gcthing"), and treats anything it finds as being in use. It may find some things that are no longer in use or that only look like a pointer to a GC-able thing (gcthing). In that case, it erroneously mark them as in use, as well as anything they point to, resulting in some garbage not getting collected. This is generally a short-term problem, however. | ||
Note that, for correctness, we only need to find a single reference to each gcthing we need to mark as being in use. This is convenient because it is common to have extra gcthing pointers that are not traced through by the GC scanner -- eg external tables, local variables and function parameters, and back pointers of various sorts. In fact, any code that does not create new gcthings or store pointers to them between calls can completely ignore the garbage collector. | Note that, for correctness, we only need to find a single reference to each gcthing we need to mark as being in use. This is convenient because it is common to have extra gcthing pointers that are not traced through by the GC scanner -- eg external tables, local variables and function parameters, and back pointers of various sorts. In fact, any code that does not create new gcthings or store pointers to them between calls can completely ignore the garbage collector. | ||
| Line 100: | Line 100: | ||
will not be traced to keep the objects live, nor will those pointers get updated on a moving GC. For local (stack-allocated) vectors, the easiest fix is to use AutoValueVector, AutoIdVector, or AutoVectorRooter<JSObject*>, which register a GC callback to trace through the vector during a GC. For heap-allocated vectors, you should convert the vectors contents to patterns of chicken entrails splattered onto a plate glass window, and infer which gcthing was intended by meditating while staring at the window while it is illuminated only by a green strobe light. | will not be traced to keep the objects live, nor will those pointers get updated on a moving GC. For local (stack-allocated) vectors, the easiest fix is to use AutoValueVector, AutoIdVector, or AutoVectorRooter<JSObject*>, which register a GC callback to trace through the vector during a GC. For heap-allocated vectors, you should convert the vectors contents to patterns of chicken entrails splattered onto a plate glass window, and infer which gcthing was intended by meditating while staring at the window while it is illuminated only by a green strobe light. | ||
== Instance Methods == | |||
One tricky case is methods on gcthings. The following code is invalid: | |||
class JSObject { | |||
void foo() { | |||
RootedObject tmp(cx, JS_NewObject(...)); | |||
...do something with data members... | |||
} | |||
}; | |||
The problem is that inside of JSObject::foo(), the 'this' pointer may be relocated, and the subsequent access of its data members will use the old pointer value. | |||
To fix this, make any method static if it could GC. This will force the gcthing pointer to be passed as a parameter, and it can then be handled normally. (An alternative would be to explicitly root 'this' at the very beginning of the method and call it eg 'self', but this is error-prone in that any reference to a data member or virtual method without a preceding 'self->' will be a GC bug.) | |||
== Performance == | == Performance == | ||