author | Terrence Cole <terrence@mozilla.com> |
Thu, 23 Apr 2015 11:05:46 -0700 | |
changeset 241319 | 2cb0f73999f485873ec72926dec2742d93da13b0 |
parent 241318 | 2f2e5313ca8e4523ccda2a381e662d116fa89919 |
child 241320 | 333aaffb8ad7eb94ff1a1cdc9f9e4cd76e16b61c |
push id | 28658 |
push user | cbook@mozilla.com |
push date | Tue, 28 Apr 2015 10:01:27 +0000 |
treeherder | mozilla-central@e0299ad29b85 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1157829 |
milestone | 40.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/gc/Marking.cpp | file | annotate | diff | comparison | revisions | |
js/src/gc/Tracer.h | file | annotate | diff | comparison | revisions |
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -324,18 +324,16 @@ typename PtrBaseGCType<T>::type* ConvertToBase(T* thingp) { return reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp); } template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name); template <typename T> T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name); template <typename T> void DoMarking(GCMarker* gcmarker, T thing); -static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell); -static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val); template <typename T> void js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name) { DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name); } @@ -580,16 +578,25 @@ js::GCMarker::markAndPush(StackTag tag, } namespace js { template <> void GCMarker::traverse(JSObject* thing) { markAndPush(ObjectTag, thing); } template <> void GCMarker::traverse(ObjectGroup* thing) { markAndPush(GroupTag, thing); } template <> void GCMarker::traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); } } // namespace js template <typename T> +void +GCMarker::traverse(JSObject* source, T* target) +{ + MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(target), + runtime()->isAtomsZone(target->zone()) || target->zone() == source->zone()); + traverse(target); +} + +template <typename T> bool js::GCMarker::mark(T* thing) { CheckTracedThing(this, thing); JS_COMPARTMENT_ASSERT(runtime(), thing); MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing))); return gc::ParticipatesInCC<T>::value ? gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor()) @@ -1425,38 +1432,16 @@ GCMarker::processMarkStackOther(uintptr_ pushValueArray(obj, vp, end); else repush(obj); } else if (tag == JitCodeTag) { reinterpret_cast<jit::JitCode*>(addr)->traceChildren(this); } } -MOZ_ALWAYS_INLINE void -GCMarker::markAndScanString(JSObject* source, JSString* str) -{ - if (!str->isPermanentAtom()) { - JS_COMPARTMENT_ASSERT(runtime(), str); - MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone()); - if (str->markIfUnmarked()) - eagerlyMarkChildren(str); - } -} - -MOZ_ALWAYS_INLINE void -GCMarker::markAndScanSymbol(JSObject* source, JS::Symbol* sym) -{ - if (!sym->isWellKnownSymbol()) { - JS_COMPARTMENT_ASSERT(runtime(), sym); - MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone()); - if (sym->markIfUnmarked()) - eagerlyMarkChildren(sym); - } -} - inline void GCMarker::processMarkStackTop(SliceBudget& budget) { /* * The function uses explicit goto and implements the scanning of the * object directly. It allows to eliminate the tail recursion and * significantly improve the marking performance, see bug 641025. */ @@ -1499,59 +1484,59 @@ GCMarker::processMarkStackTop(SliceBudge budget.step(); if (budget.isOverBudget()) { pushValueArray(obj, vp, end); return; } const Value& v = *vp++; if (v.isString()) { - markAndScanString(obj, v.toString()); + traverse(obj, v.toString()); } else if (v.isObject()) { JSObject* obj2 = &v.toObject(); MOZ_ASSERT(obj->compartment() == obj2->compartment()); if (mark(obj2)) { // Save the rest of this value array for later and start scanning obj2's children.N pushValueArray(obj, vp, end); obj = obj2; goto scan_obj; } } else if (v.isSymbol()) { - markAndScanSymbol(obj, v.toSymbol()); + traverse(obj, v.toSymbol()); } } return; scan_unboxed: { while (*unboxedTraceList != -1) { JSString* str = *reinterpret_cast<JSString**>(unboxedMemory + *unboxedTraceList); - markAndScanString(obj, str); + traverse(obj, str); unboxedTraceList++; } unboxedTraceList++; while (*unboxedTraceList != -1) { JSObject* obj2 = *reinterpret_cast<JSObject**>(unboxedMemory + *unboxedTraceList); MOZ_ASSERT_IF(obj2, obj->compartment() == obj2->compartment()); if (obj2 && mark(obj2)) repush(obj2); unboxedTraceList++; } unboxedTraceList++; while (*unboxedTraceList != -1) { const Value& v = *reinterpret_cast<Value*>(unboxedMemory + *unboxedTraceList); if (v.isString()) { - markAndScanString(obj, v.toString()); + traverse(obj, v.toString()); } else if (v.isObject()) { JSObject* obj2 = &v.toObject(); MOZ_ASSERT(obj->compartment() == obj2->compartment()); if (mark(obj2)) repush(obj2); } else if (v.isSymbol()) { - markAndScanSymbol(obj, v.toSymbol()); + traverse(obj, v.toSymbol()); } unboxedTraceList++; } return; } scan_obj: {
--- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -155,16 +155,19 @@ class GCMarker : public JSTracer void start(); void stop(); void reset(); // Mark the given GC thing and traverse its children at some point. template <typename T> void traverse(T* thing); + // Calls traverse on target after making additional assertions. + template <typename T> void traverse(JSObject* source, T* target); + /* * Care must be taken changing the mark color from gray to black. The cycle * collector depends on the invariant that there are no black to gray edges * in the GC heap. This invariant lets the CC not trace through black * objects. If this invariant is violated, the cycle collector may free * objects that are still reachable. */ void setMarkColorGray() { @@ -280,19 +283,16 @@ class GCMarker : public JSTracer return stack.isEmpty(); } bool restoreValueArray(NativeObject* obj, void** vpp, void** endp); void saveValueRanges(); inline void processMarkStackTop(SliceBudget& budget); void processMarkStackOther(uintptr_t tag, uintptr_t addr); - void markAndScanString(JSObject* source, JSString* str); - void markAndScanSymbol(JSObject* source, JS::Symbol* sym); - /* The color is only applied to objects and functions. */ uint32_t color; /* Pointer to the top of the stack of arenas we are delaying marking on. */ js::gc::ArenaHeader* unmarkedArenaStackTop; /* Count of arenas that are currently in the stack. */ mozilla::DebugOnly<size_t> markLaterArenas;