diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h index 66b66c2b679a..47bc708219d1 100644 --- a/js/src/gc/GCInternals.h +++ b/js/src/gc/GCInternals.h @@ -138,7 +138,7 @@ CheckHashTablesAfterMovingGC(JSRuntime *rt); #ifdef JSGC_COMPACTING struct MovingTracer : JSTracer { - MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapValues) {} + MovingTracer(JSRuntime *rt) : JSTracer(rt, Visit, TraceWeakMapKeysValues) {} static void Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind); static void Sweep(JSTracer *jstrc); diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 0758d12b7d91..ac7757701780 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -538,6 +538,8 @@ struct ArenaHeader : public JS::shadow::ArenaHeader inline ArenaHeader *getNextAllocDuringSweep() const; inline void setNextAllocDuringSweep(ArenaHeader *aheader); inline void unsetAllocDuringSweep(); + + void unmarkAll(); }; struct Arena diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index c57969833633..6d532ee4ae9a 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -447,6 +447,13 @@ ArenaHeader::checkSynchronizedWithFreeList() const } #endif +void +ArenaHeader::unmarkAll() +{ + uintptr_t *word = chunk()->bitmap.arenaBits(this); + memset(word, 0, ArenaBitmapWords * sizeof(uintptr_t)); +} + /* static */ void Arena::staticAsserts() { @@ -2483,6 +2490,9 @@ GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList) ArenaHeader *aheader = relocatedList; relocatedList = relocatedList->next; + // Clear the mark bits + aheader->unmarkAll(); + // Mark arena as empty AllocKind thingKind = aheader->getAllocKind(); size_t thingSize = aheader->getThingSize(); diff --git a/js/src/jsgc.h b/js/src/jsgc.h index e9c816d69841..2c13f4fdf2f1 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -726,10 +726,8 @@ class ArenaLists /* The background finalization must have stopped at this point. */ JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE || backgroundFinalizeState[i] == BFS_JUST_FINISHED); - for (ArenaHeader *aheader = arenaLists[i].head(); aheader; aheader = aheader->next) { - uintptr_t *word = aheader->chunk()->bitmap.arenaBits(aheader); - memset(word, 0, ArenaBitmapWords * sizeof(uintptr_t)); - } + for (ArenaHeader *aheader = arenaLists[i].head(); aheader; aheader = aheader->next) + aheader->unmarkAll(); } } diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index bc58a55eb44a..1408f10eb2d2 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -662,6 +662,12 @@ JSObject::finish(js::FreeOp *fop) fop->free_(elements); } } + + // It's possible that unreachable shapes may be marked whose listp points + // into this object. In case this happens, null out the shape's pointer here + // so that a moving GC will not try to access the dead object. + if (shape_->listp == &shape_) + shape_->listp = nullptr; } /* static */ inline bool diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 3bb49070f001..48640d674530 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -71,8 +71,12 @@ WeakMapBase::unmarkCompartment(JSCompartment *c) void WeakMapBase::markAll(JSCompartment *c, JSTracer *tracer) { - for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) - m->markIteratively(tracer); + JS_ASSERT(tracer->eagerlyTraceWeakMaps() != DoNotTraceWeakMaps); + for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) { + m->trace(tracer); + if (m->memberOf) + gc::MarkObject(tracer, &m->memberOf, "memberOf"); + } } bool diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 07fa008fc61f..e1900aeba659 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -91,7 +91,7 @@ class WeakMapBase { virtual void finish() = 0; // Object that this weak map is part of, if any. - JSObject *memberOf; + HeapPtrObject memberOf; // Compartment that this weak map is part of. JSCompartment *compartment; diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index 1739410fffef..13beff56859c 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -772,10 +772,13 @@ RegExpCompartment::sweep(JSRuntime *rt) bool keep = shared->marked() && !IsStringAboutToBeFinalized(shared->source.unsafeGet()); for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) { RegExpShared::RegExpCompilation &compilation = shared->compilationArray[i]; - if (keep && compilation.jitCode) - keep = !IsJitCodeAboutToBeFinalized(compilation.jitCode.unsafeGet()); + if (compilation.jitCode && + IsJitCodeAboutToBeFinalized(compilation.jitCode.unsafeGet())) + { + keep = false; + } } - if (keep) { + if (keep || rt->isHeapCompacting()) { shared->clearMarked(); } else { js_delete(shared); diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index a5bdfae69a8c..7e5fd4121b65 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -199,7 +199,7 @@ class RegExpShared void trace(JSTracer *trc); bool marked() const { return marked_; } - void clearMarked() { JS_ASSERT(marked_); marked_ = false; } + void clearMarked() { marked_ = false; } size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); };