Bug 690970, part 1: unmark gray read barrier for weak maps. r=billm

This commit is contained in:
Andrew McCreight 2013-01-08 10:36:51 -08:00
parent 01ce1f1e3d
commit 0ea7b9fd4d
3 changed files with 26 additions and 0 deletions

View File

@ -157,6 +157,13 @@ ExposeGCThingToActiveJS(void *thing, JSGCTraceKind kind)
js::IncrementalReferenceBarrier(thing);
}
static JS_ALWAYS_INLINE void
ExposeValueToActiveJS(const Value &v)
{
if (v.isMarkable())
ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
}
} /* namespace JS */
#endif /* js_heap_api_h___ */

View File

@ -1569,6 +1569,21 @@ struct UnmarkGrayTracer : public JSTracer
* black in step 2 above. This must be done on everything reachable from the
* object being returned. The following code takes care of the recursive
* re-coloring.
*
* There is an additional complication for certain kinds of edges that are not
* contained explicitly in the source object itself, such as from a weakmap key
* to its value, and from an object being watched by a watchpoint to the
* watchpoint's closure. These "implicit edges" are represented in some other
* container object, such as the weakmap or the watchpoint itself. In these
* cases, calling unmark gray on an object won't find all of its children.
*
* Handling these implicit edges has two parts:
* - A special pass enumerating all of the containers that know about the
* implicit edges to fix any black-gray edges that have been created. This
* is implemented in nsXPConnect::FixWeakMappingGrayBits.
* - To prevent any incorrectly gray objects from escaping to live JS outside
* of the containers, we must add unmark-graying read barriers to these
* containers.
*/
static void
UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)

View File

@ -209,6 +209,10 @@ WeakMap_get_impl(JSContext *cx, CallArgs args)
if (ObjectValueMap *map = GetObjectMap(&args.thisv().toObject())) {
if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
// Read barrier to prevent an incorrectly gray value from escaping the
// weak map. See the comment before UnmarkGrayChildren in gc/Marking.cpp
ExposeValueToActiveJS(ptr->value.get());
args.rval().set(ptr->value);
return true;
}