author | Bill McCloskey <wmccloskey@mozilla.com> |
Mon, 27 Feb 2012 09:48:35 -0800 | |
changeset 87848 | 246c77eef7cbb6febbdd3c7660b6143eb0093e99 |
parent 87847 | 0714ec049da2e9a9a6f7bf6f2cf7233528d1e76e |
child 87849 | 00929ec6099170cb7c22169bf9ea5e7db85630f2 |
push id | 22160 |
push user | mbrubeck@mozilla.com |
push date | Tue, 28 Feb 2012 17:21:33 +0000 |
treeherder | mozilla-central@dde4e0089a18 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | igor |
bugs | 729238 |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jsgc.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsweakmap.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsweakmap.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3073,37 +3073,45 @@ ValidateIncrementalMarking(JSContext *cx typedef HashMap<Chunk *, uintptr_t *, GCChunkHasher, SystemAllocPolicy> BitmapMap; BitmapMap map; if (!map.init()) return; JSRuntime *rt = cx->runtime; FullGCMarker *gcmarker = &rt->gcMarker; - /* Save existing mark bits */ + /* Save existing mark bits. */ for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) { ChunkBitmap *bitmap = &r.front()->bitmap; uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap)); if (!entry) return; memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap)); if (!map.putNew(r.front(), entry)) return; } + /* Save the existing weakmaps. */ + WeakMapVector weakmaps; + if (!WeakMapBase::saveWeakMapList(rt, weakmaps)) + return; + /* * After this point, the function should run to completion, so we shouldn't * do anything fallible. */ /* Re-do all the marking, but non-incrementally. */ js::gc::State state = rt->gcIncrementalState; rt->gcIncrementalState = NO_INCREMENTAL; + /* As we're re-doing marking, we need to reset the weak map list. */ + WeakMapBase::resetWeakMapList(rt); + JS_ASSERT(gcmarker->isDrained()); gcmarker->reset(); for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) r.front()->bitmap.clear(); MarkRuntime(gcmarker, true); SliceBudget budget; @@ -3141,16 +3149,20 @@ ValidateIncrementalMarking(JSContext *cx JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap.isMarked(cell, BLACK)); thing += Arena::thingSize(kind); } } memcpy(bitmap->bitmap, incBitmap.bitmap, sizeof(incBitmap.bitmap)); } + /* Restore the weak map list. */ + WeakMapBase::resetWeakMapList(rt); + WeakMapBase::restoreWeakMapList(rt, weakmaps); + rt->gcIncrementalState = state; } #endif static void SweepPhase(JSContext *cx, JSGCInvocationKind gckind) { JSRuntime *rt = cx->runtime;
--- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -97,16 +97,40 @@ WeakMapBase::resetWeakMapList(JSRuntime rt->gcWeakMapList = NULL; while (m) { WeakMapBase *n = m->next; m->next = WeakMapNotInList; m = n; } } +bool +WeakMapBase::saveWeakMapList(JSRuntime *rt, WeakMapVector &vector) +{ + WeakMapBase *m = rt->gcWeakMapList; + while (m) { + if (!vector.append(m)) + return false; + m = m->next; + } + return true; +} + +void +WeakMapBase::restoreWeakMapList(JSRuntime *rt, WeakMapVector &vector) +{ + JS_ASSERT(!rt->gcWeakMapList); + for (WeakMapBase **p = vector.begin(); p != vector.end(); p++) { + WeakMapBase *m = *p; + JS_ASSERT(m->next == WeakMapNotInList); + m->next = rt->gcWeakMapList; + rt->gcWeakMapList = m; + } +} + } /* namespace js */ typedef WeakMap<HeapPtr<JSObject>, HeapValue> ObjectValueMap; static ObjectValueMap * GetObjectMap(JSObject *obj) { JS_ASSERT(obj->isWeakMap());
--- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -104,16 +104,18 @@ template <class Type> class DefaultMarkP // A policy template holding default tracing algorithms for common type combinations. This // provides default types for WeakMap's TracePolicy template parameter. template <class Key, class Value> class DefaultTracePolicy; // The value for the next pointer for maps not in the map list. static WeakMapBase * const WeakMapNotInList = reinterpret_cast<WeakMapBase *>(1); +typedef Vector<WeakMapBase *, 0, SystemAllocPolicy> WeakMapVector; + // Common base class for all WeakMap specializations. The collector uses this to call // their markIteratively and sweep methods. class WeakMapBase { public: WeakMapBase(JSObject *memOf) : memberOf(memOf), next(WeakMapNotInList) { } virtual ~WeakMapBase() { } void trace(JSTracer *tracer) { @@ -156,16 +158,20 @@ class WeakMapBase { // Trace all delayed weak map bindings. Used by the cycle collector. static void traceAllMappings(WeakMapTracer *tracer); void check() { JS_ASSERT(next == WeakMapNotInList); } // Remove everything from the live weak map list. static void resetWeakMapList(JSRuntime *rt); + // Save and restore the live weak map list to a vector. + static bool saveWeakMapList(JSRuntime *rt, WeakMapVector &vector); + static void restoreWeakMapList(JSRuntime *rt, WeakMapVector &vector); + protected: // Instance member functions called by the above. Instantiations of WeakMap override // these with definitions appropriate for their Key and Value types. virtual void nonMarkingTrace(JSTracer *tracer) = 0; virtual bool markIteratively(JSTracer *tracer) = 0; virtual void sweep(JSTracer *tracer) = 0; virtual void traceMappings(WeakMapTracer *tracer) = 0;