Bug 726687 - GC: rewrite key marking in terms of HashMap::rekey r=terrence

This commit is contained in:
Jon Coppeard 2013-02-15 10:42:39 +00:00
parent 89e4b5ccde
commit 2eb25384eb
4 changed files with 31 additions and 23 deletions

View File

@ -490,9 +490,10 @@ AutoGCRooter::trace(JSTracer *trc)
AutoObjectUnsigned32HashMap *self = static_cast<AutoObjectUnsigned32HashMap *>(this);
AutoObjectUnsigned32HashMap::HashMapImpl &map = self->map;
for (AutoObjectUnsigned32HashMap::Enum e(map); !e.empty(); e.popFront()) {
mozilla::DebugOnly<JSObject *> key = e.front().key;
MarkObjectRoot(trc, const_cast<JSObject **>(&e.front().key), "AutoObjectUnsignedHashMap key");
JS_ASSERT(key == e.front().key); // Needs rewriting for moving GC, see bug 726687.
JSObject *key = e.front().key;
MarkObjectRoot(trc, &key, "AutoObjectUnsignedHashMap key");
if (key != e.front().key)
e.rekeyFront(key);
}
return;
}
@ -501,9 +502,10 @@ AutoGCRooter::trace(JSTracer *trc)
AutoObjectHashSet *self = static_cast<AutoObjectHashSet *>(this);
AutoObjectHashSet::HashSetImpl &set = self->set;
for (AutoObjectHashSet::Enum e(set); !e.empty(); e.popFront()) {
mozilla::DebugOnly<JSObject *> obj = e.front();
MarkObjectRoot(trc, const_cast<JSObject **>(&e.front()), "AutoObjectHashSet value");
JS_ASSERT(obj == e.front()); // Needs rewriting for moving GC, see bug 726687.
JSObject *obj = e.front();
MarkObjectRoot(trc, &obj, "AutoObjectHashSet value");
if (obj != e.front())
e.rekeyFront(obj);
}
return;
}

View File

@ -181,14 +181,16 @@ void
js::MarkAtoms(JSTracer *trc)
{
JSRuntime *rt = trc->runtime;
for (AtomSet::Range r = rt->atoms().all(); !r.empty(); r.popFront()) {
AtomStateEntry entry = r.front();
for (AtomSet::Enum e(rt->atoms()); !e.empty(); e.popFront()) {
const AtomStateEntry &entry = e.front();
if (!entry.isTagged())
continue;
JSAtom *tmp = entry.asPtr();
MarkStringRoot(trc, &tmp, "interned_atom");
JS_ASSERT(tmp == entry.asPtr());
JSAtom *atom = entry.asPtr();
bool tagged = entry.isTagged();
MarkStringRoot(trc, &atom, "interned_atom");
if (entry.asPtr() != atom)
e.rekeyFront(AtomHasher::Lookup(atom), AtomStateEntry(atom, tagged));
}
}

View File

@ -180,19 +180,20 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
bool markedAny = false;
for (Enum e(*this); !e.empty(); e.popFront()) {
/* If the entry is live, ensure its key and value are marked. */
Key prior(e.front().key);
if (gc::IsMarked(const_cast<Key *>(&e.front().key))) {
Key key(e.front().key);
if (gc::IsMarked(const_cast<Key *>(&key))) {
if (markValue(trc, &e.front().value))
markedAny = true;
if (prior != e.front().key)
e.rekeyFront(e.front().key);
} else if (keyNeedsMark(e.front().key)) {
gc::Mark(trc, const_cast<Key *>(&e.front().key), "proxy-preserved WeakMap entry key");
if (prior != e.front().key)
e.rekeyFront(e.front().key);
if (e.front().key != key)
e.rekeyFront(key);
} else if (keyNeedsMark(key)) {
gc::Mark(trc, const_cast<Key *>(&key), "proxy-preserved WeakMap entry key");
if (e.front().key != key)
e.rekeyFront(key);
gc::Mark(trc, &e.front().value, "WeakMap entry value");
markedAny = true;
}
key.unsafeSet(NULL);
}
return markedAny;
}

View File

@ -58,6 +58,7 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
public:
/* Expose those parts of HashMap public interface that are used by Debugger methods. */
typedef typename Base::Entry Entry;
typedef typename Base::Ptr Ptr;
typedef typename Base::AddPtr AddPtr;
typedef typename Base::Range Range;
@ -104,10 +105,12 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
public:
void markKeys(JSTracer *tracer) {
for (Range r = all(); !r.empty(); r.popFront()) {
Key key = r.front().key;
gc::Mark(tracer, &key, "cross-compartment WeakMap key");
JS_ASSERT(key == r.front().key);
for (Enum e(*static_cast<Base *>(this)); !e.empty(); e.popFront()) {
Key key = e.front().key;
gc::Mark(tracer, &key, "Debugger WeakMap key");
if (key != e.front().key)
e.rekeyFront(key);
key.unsafeSet(NULL);
}
}