From 84ec03bf151130b0f3fc5abc872959553aa80e92 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Thu, 12 Apr 2018 16:35:26 +0200 Subject: [PATCH] Bug 1452982 part 3 - Remove ZoneGroup nursery/storeBuffer methods. r=jonco --- js/src/builtin/DataViewObject.cpp | 2 +- js/src/builtin/MapObject.cpp | 11 +++-- js/src/builtin/TestingFunctions.cpp | 2 +- js/src/builtin/TypedObject.cpp | 8 ++-- js/src/gc/GC-inl.h | 3 +- js/src/gc/GC.cpp | 44 +++++------------- js/src/gc/Nursery-inl.h | 6 --- js/src/gc/RootMarking.cpp | 4 +- js/src/gc/StoreBuffer.cpp | 6 +-- js/src/gc/Zone.h | 4 +- js/src/gc/ZoneGroup.h | 6 --- js/src/jit/CodeGenerator.cpp | 2 +- js/src/jit/CompileWrappers.cpp | 7 +-- js/src/jit/Ion.cpp | 2 +- js/src/jit/IonBuilder.cpp | 2 +- js/src/jit/JitFrames.cpp | 6 +-- js/src/jit/Linker.cpp | 2 +- js/src/jit/MIR.cpp | 4 +- js/src/jit/VMFunctions.cpp | 4 +- js/src/jit/shared/CodeGenerator-shared.cpp | 3 +- js/src/jsfriendapi.cpp | 2 +- js/src/proxy/CrossCompartmentWrapper.cpp | 2 +- js/src/vm/ArgumentsObject.cpp | 2 +- js/src/vm/ArrayBufferObject.cpp | 2 +- js/src/vm/JSObject.cpp | 14 +++--- js/src/vm/NativeObject-inl.h | 7 +-- js/src/vm/Runtime.h | 12 ----- js/src/vm/StringType.cpp | 4 +- js/src/vm/TypeInference.cpp | 4 +- js/src/vm/TypedArrayObject.cpp | 4 +- js/src/vm/UnboxedObject-inl.h | 54 ++-------------------- js/src/vm/UnboxedObject.cpp | 4 +- 32 files changed, 76 insertions(+), 163 deletions(-) diff --git a/js/src/builtin/DataViewObject.cpp b/js/src/builtin/DataViewObject.cpp index 7ea2ba3e0302..5bf38f50f2b4 100644 --- a/js/src/builtin/DataViewObject.cpp +++ b/js/src/builtin/DataViewObject.cpp @@ -92,7 +92,7 @@ DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength, MOZ_ASSERT(arrayBuffer->byteLength() == 0 && (uintptr_t(ptr.unwrapValue()) & gc::ChunkMask) == 0); } else { - cx->zone()->group()->storeBuffer().putWholeCell(obj); + cx->runtime()->gc.storeBuffer().putWholeCell(obj); } } diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 37e1f15d083f..c4a8d53d3778 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -266,7 +266,7 @@ MapIteratorObject::finalize(FreeOp* fop, JSObject* obj) MOZ_ASSERT(!IsInsideNursery(obj)); auto range = MapIteratorObjectRange(&obj->as()); - MOZ_ASSERT(!obj->zone()->group()->nursery().isInside(range)); + MOZ_ASSERT(!fop->runtime()->gc.nursery().isInside(range)); fop->delete_(range); } @@ -282,7 +282,7 @@ MapIteratorObject::objectMoved(JSObject* obj, JSObject* old) if (!range) return 0; - Nursery& nursery = iter->zone()->group()->nursery(); + Nursery& nursery = iter->runtimeFromActiveCooperatingThread()->gc.nursery(); if (!nursery.isInside(range)) { nursery.removeMallocedBuffer(range); return 0; @@ -567,7 +567,8 @@ WriteBarrierPostImpl(ObjectT* obj, const Value& keyValue) if (!keys) return false; - key->zone()->group()->storeBuffer().putGeneric(OrderedHashTableRef(obj)); + JSRuntime* rt = key->runtimeFromActiveCooperatingThread(); + rt->gc.storeBuffer().putGeneric(OrderedHashTableRef(obj)); } if (!keys->append(key)) @@ -1116,7 +1117,7 @@ SetIteratorObject::finalize(FreeOp* fop, JSObject* obj) MOZ_ASSERT(!IsInsideNursery(obj)); auto range = SetIteratorObjectRange(&obj->as()); - MOZ_ASSERT(!obj->zone()->group()->nursery().isInside(range)); + MOZ_ASSERT(!fop->runtime()->gc.nursery().isInside(range)); fop->delete_(range); } @@ -1132,7 +1133,7 @@ SetIteratorObject::objectMoved(JSObject* obj, JSObject* old) if (!range) return 0; - Nursery& nursery = iter->zone()->group()->nursery(); + Nursery& nursery = iter->runtimeFromActiveCooperatingThread()->gc.nursery(); if (!nursery.isInside(range)) { nursery.removeMallocedBuffer(range); return 0; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index d291cbe3e0d8..f0a304f1f84c 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -352,7 +352,7 @@ MinorGC(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.get(0) == BooleanValue(true)) - cx->zone()->group()->storeBuffer().setAboutToOverflow(JS::gcreason::FULL_GENERIC_BUFFER); + cx->runtime()->gc.storeBuffer().setAboutToOverflow(JS::gcreason::FULL_GENERIC_BUFFER); cx->minorGC(JS::gcreason::API); args.rval().setUndefined(); diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index aa2aa23381ca..24481082bb05 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -1434,7 +1434,7 @@ OutlineTypedObject::setOwnerAndData(JSObject* owner, uint8_t* data) // Trigger a post barrier when attaching an object outside the nursery to // one that is inside it. if (owner && !IsInsideNursery(this) && IsInsideNursery(owner)) - zone()->group()->storeBuffer().putWholeCell(this); + owner->storeBuffer()->putWholeCell(this); } /*static*/ OutlineTypedObject* @@ -1634,7 +1634,7 @@ OutlineTypedObject::obj_trace(JSTracer* trc, JSObject* object) typedObj.setData(newData); if (trc->isTenuringTracer()) { - Nursery& nursery = typedObj.zoneFromAnyThread()->group()->nursery(); + Nursery& nursery = trc->runtime()->gc.nursery(); nursery.maybeSetForwardingPointer(trc, oldData, newData, /* direct = */ false); } } @@ -2144,7 +2144,7 @@ InlineTypedObject::obj_moved(JSObject* dst, JSObject* src) // but they will not set any direct forwarding pointers. uint8_t* oldData = reinterpret_cast(src) + offsetOfDataStart(); uint8_t* newData = dst->as().inlineTypedMem(); - auto& nursery = dst->zone()->group()->nursery(); + auto& nursery = dst->runtimeFromActiveCooperatingThread()->gc.nursery(); bool direct = descr.size() >= sizeof(uintptr_t); nursery.setForwardingPointerWhileTenuring(oldData, newData, direct); } @@ -2195,7 +2195,7 @@ InlineTransparentTypedObject::getOrCreateBuffer(JSContext* cx) if (IsInsideNursery(this)) { // Make sure the buffer is traced by the next generational collection, // so that its data pointer is updated after this typed object moves. - zone()->group()->storeBuffer().putWholeCell(buffer); + storeBuffer()->putWholeCell(buffer); } return buffer; diff --git a/js/src/gc/GC-inl.h b/js/src/gc/GC-inl.h index d2ffa52e14b7..02bb8eb6fbc1 100644 --- a/js/src/gc/GC-inl.h +++ b/js/src/gc/GC-inl.h @@ -207,7 +207,8 @@ class ZoneCellIter { void init(JS::Zone* zone, AllocKind kind) { MOZ_ASSERT_IF(IsNurseryAllocable(kind), - zone->isAtomsZone() || zone->group()->nursery().isEmpty()); + (zone->isAtomsZone() || + zone->runtimeFromActiveCooperatingThread()->gc.nursery().isEmpty())); initForTenuredIteration(zone, kind); } diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index d2d5f2beb1d8..93b1e51c6c3d 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1065,10 +1065,8 @@ GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) } ZealMode zealMode = ZealMode(zeal); - if (zealMode == ZealMode::GenerationalGC) { - for (ZoneGroupsIter group(rt); !group.done(); group.next()) - group->nursery().enterZealMode(); - } + if (zealMode == ZealMode::GenerationalGC) + nursery().enterZealMode(); // Some modes are mutually exclusive. If we're setting one of those, we // first reset all of them. @@ -1282,8 +1280,7 @@ GCRuntime::finish() FinishTrace(); - for (ZoneGroupsIter group(rt); !group.done(); group.next()) - group->nursery().printTotalProfileTimes(); + nursery().printTotalProfileTimes(); stats().printTotalProfileTimes(); } @@ -6609,7 +6606,7 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget, Zone* zone = zonesToMaybeCompact.ref().front(); zonesToMaybeCompact.ref().removeFront(); - MOZ_ASSERT(zone->group()->nursery().isEmpty()); + MOZ_ASSERT(nursery().isEmpty()); zone->changeGCState(Zone::Finished, Zone::Compact); if (relocateArenas(zone, reason, relocatedArenas, sliceBudget)) { @@ -6699,18 +6696,6 @@ HeapStateToLabel(JS::HeapState heapState) return nullptr; } -#ifdef DEBUG -static bool -AllNurseriesAreEmpty(JSRuntime* rt) -{ - for (ZoneGroupsIter group(rt); !group.done(); group.next()) { - if (!group->nursery().isEmpty()) - return false; - } - return true; -} -#endif - /* Start a new heap session. */ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState) : runtime(rt), @@ -6720,7 +6705,7 @@ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState) { MOZ_ASSERT(prevState == JS::HeapState::Idle); MOZ_ASSERT(heapState != JS::HeapState::Idle); - MOZ_ASSERT_IF(heapState == JS::HeapState::MajorCollecting, AllNurseriesAreEmpty(rt)); + MOZ_ASSERT_IF(heapState == JS::HeapState::MajorCollecting, rt->gc.nursery().isEmpty()); // Session always begins with lock held, see comment in class definition. maybeLock.emplace(rt); @@ -7691,8 +7676,7 @@ GCRuntime::onOutOfMallocMemory() decommitTask.join(); // Wait for background free of nursery huge slots to finish. - for (ZoneGroupsIter group(rt); !group.done(); group.next()) - group->nursery().waitBackgroundFreeEnd(); + nursery().waitBackgroundFreeEnd(); AutoLockGC lock(rt); onOutOfMallocMemory(lock); @@ -7756,10 +7740,8 @@ JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSContext* cx) JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() { - if (--cx->generationalDisabled == 0) { - for (ZoneGroupsIter group(cx->runtime()); !group.done(); group.next()) - group->nursery().enable(); - } + if (--cx->generationalDisabled == 0) + cx->nursery().enable(); } JS_PUBLIC_API(bool) @@ -7804,8 +7786,7 @@ js::gc::FinishGC(JSContext* cx) JS::FinishIncrementalGC(cx, JS::gcreason::API); } - for (ZoneGroupsIter group(cx->runtime()); !group.done(); group.next()) - group->nursery().waitBackgroundFreeEnd(); + cx->nursery().waitBackgroundFreeEnd(); } AutoPrepareForTracing::AutoPrepareForTracing(JSContext* cx) @@ -7858,9 +7839,6 @@ js::NewCompartment(JSContext* cx, JSPrincipals* principals, return nullptr; groupHolder.reset(group); - - if (cx->generationalDisabled) - group->nursery().disable(); } if (!zone) { @@ -8942,7 +8920,7 @@ AutoAssertEmptyNursery::checkCondition(JSContext* cx) { if (!noAlloc) noAlloc.emplace(); this->cx = cx; - MOZ_ASSERT(AllNurseriesAreEmpty(cx->runtime())); + MOZ_ASSERT(cx->nursery().isEmpty()); } AutoEmptyNursery::AutoEmptyNursery(JSContext* cx) @@ -8950,7 +8928,7 @@ AutoEmptyNursery::AutoEmptyNursery(JSContext* cx) { MOZ_ASSERT(!cx->suppressGC); cx->runtime()->gc.stats().suspendPhases(); - EvictAllNurseries(cx->runtime(), JS::gcreason::EVICT_NURSERY); + cx->runtime()->gc.evictNursery(JS::gcreason::EVICT_NURSERY); cx->runtime()->gc.stats().resumePhases(); checkCondition(cx); } diff --git a/js/src/gc/Nursery-inl.h b/js/src/gc/Nursery-inl.h index 247ac75dbb00..25d83b177c6a 100644 --- a/js/src/gc/Nursery-inl.h +++ b/js/src/gc/Nursery-inl.h @@ -139,12 +139,6 @@ ReallocateObjectBuffer(JSContext* cx, JSObject* obj, T* oldBuffer, return buffer; } -static inline void -EvictAllNurseries(JSRuntime* rt, JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) -{ - rt->gc.evictNursery(reason); -} - } // namespace js #endif /* gc_Nursery_inl_h */ diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 346c2722ecbf..18dbc7b8cbc6 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -284,8 +284,8 @@ js::TraceRuntime(JSTracer* trc) MOZ_ASSERT(!trc->isMarkingTracer()); JSRuntime* rt = trc->runtime(); - EvictAllNurseries(rt); - AutoPrepareForTracing prep(TlsContext.get()); + rt->gc.evictNursery(); + AutoPrepareForTracing prep(rt->mainContextFromOwnThread()); gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::TRACE_HEAP); rt->gc.traceRuntime(trc, prep.session()); } diff --git a/js/src/gc/StoreBuffer.cpp b/js/src/gc/StoreBuffer.cpp index 35dad31bacf3..2652f0542de2 100644 --- a/js/src/gc/StoreBuffer.cpp +++ b/js/src/gc/StoreBuffer.cpp @@ -138,8 +138,8 @@ ArenaCellSet* StoreBuffer::WholeCellBuffer::allocateCellSet(Arena* arena) { Zone* zone = arena->zone; - Nursery& nursery = zone->group()->nursery(); - if (!nursery.isEnabled()) + JSRuntime* rt = zone->runtimeFromActiveCooperatingThread(); + if (!rt->gc.nursery().isEnabled()) return nullptr; AutoEnterOOMUnsafeRegion oomUnsafe; @@ -151,7 +151,7 @@ StoreBuffer::WholeCellBuffer::allocateCellSet(Arena* arena) head_ = cells; if (isAboutToOverflow()) - zone->group()->storeBuffer().setAboutToOverflow(JS::gcreason::FULL_WHOLE_CELL_BUFFER); + rt->gc.storeBuffer().setAboutToOverflow(JS::gcreason::FULL_WHOLE_CELL_BUFFER); return cells; } diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 2fd087a1ea49..cdd70da55bd0 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -582,7 +582,9 @@ struct Zone : public JS::shadow::Zone, // If the cell was in the nursery, hopefully unlikely, then we need to // tell the nursery about it so that it can sweep the uid if the thing // does not get tenured. - if (IsInsideNursery(cell) && !group()->nursery().addedUniqueIdToCell(cell)) { + if (IsInsideNursery(cell) && + !runtimeFromActiveCooperatingThread()->gc.nursery().addedUniqueIdToCell(cell)) + { uniqueIds().remove(cell); return false; } diff --git a/js/src/gc/ZoneGroup.h b/js/src/gc/ZoneGroup.h index ef64113e9dec..6253d757f73c 100644 --- a/js/src/gc/ZoneGroup.h +++ b/js/src/gc/ZoneGroup.h @@ -82,12 +82,6 @@ class ZoneGroup explicit ZoneGroup(JSRuntime* runtime); ~ZoneGroup(); - inline Nursery& nursery(); - inline gc::StoreBuffer& storeBuffer(); - - inline bool isCollecting(); - inline bool isGCScheduled(); - // Delete an empty zone after its contents have been merged. void deleteEmptyZone(Zone* zone); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index e91a72830b9b..131f0dccd741 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -10488,7 +10488,7 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints) for (size_t i = 0; i < graph.numConstants(); i++) { const Value& v = vp[i]; if ((v.isObject() || v.isString()) && IsInsideNursery(v.toGCThing())) { - cx->zone()->group()->storeBuffer().putWholeCell(script); + cx->runtime()->gc.storeBuffer().putWholeCell(script); break; } } diff --git a/js/src/jit/CompileWrappers.cpp b/js/src/jit/CompileWrappers.cpp index b98093c18a18..156d6fad5a9b 100644 --- a/js/src/jit/CompileWrappers.cpp +++ b/js/src/jit/CompileWrappers.cpp @@ -212,21 +212,22 @@ bool CompileZone::canNurseryAllocateStrings() { return nurseryExists() && - zone()->group()->nursery().canAllocateStrings() && + zone()->runtimeFromAnyThread()->gc.nursery().canAllocateStrings() && zone()->allocNurseryStrings; } bool CompileZone::nurseryExists() { - return zone()->group()->nursery().exists(); + return zone()->runtimeFromAnyThread()->gc.nursery().exists(); } void CompileZone::setMinorGCShouldCancelIonCompilations() { MOZ_ASSERT(CurrentThreadCanAccessZone(zone())); - zone()->group()->storeBuffer().setShouldCancelIonCompilations(); + JSRuntime* rt = zone()->runtimeFromActiveCooperatingThread(); + rt->gc.storeBuffer().setShouldCancelIonCompilations(); } JSCompartment* diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index a490a7cd3fdb..aebe0250df4d 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -2086,7 +2086,7 @@ IonCompile(JSContext* cx, JSScript* script, if (!builder) return AbortReason::Alloc; - if (cx->zone()->group()->storeBuffer().cancelIonCompilations()) + if (cx->runtime()->gc.storeBuffer().cancelIonCompilations()) builder->setNotSafeForMinorGC(); MOZ_ASSERT(recompile == builder->script()->hasIonScript()); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 8cb1bec47782..c9eea590f0bc 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -8647,7 +8647,7 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj, SharedMem data = tarr->as().viewDataEither(); // Bug 979449 - Optimistically embed the elements and use TI to // invalidate if we move them. - bool isTenured = !tarr->zone()->group()->nursery().isInside(data); + bool isTenured = !tarr->runtimeFromActiveCooperatingThread()->gc.nursery().isInside(data); if (isTenured && tarr->isSingleton()) { // The 'data' pointer of TypedArrayObject can change in rare circumstances // (ArrayBufferObject::changeContents). diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index e31d4fa4c5cb..4025692ea18f 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -975,7 +975,7 @@ TraceBailoutFrame(JSTracer* trc, const JSJitFrameIter& frame) } static void -UpdateIonJSFrameForMinorGC(const JSJitFrameIter& frame) +UpdateIonJSFrameForMinorGC(JSRuntime* rt, const JSJitFrameIter& frame) { // Minor GCs may move slots/elements allocated in the nursery. Update // any slots/elements pointers stored in this frame. @@ -991,7 +991,7 @@ UpdateIonJSFrameForMinorGC(const JSJitFrameIter& frame) ionScript = frame.ionScriptFromCalleeToken(); } - Nursery& nursery = ionScript->method()->zone()->group()->nursery(); + Nursery& nursery = rt->gc.nursery(); const SafepointIndex* si = ionScript->getSafepointIndex(frame.returnAddressToFp()); SafepointReader safepoint(ionScript, si); @@ -1315,7 +1315,7 @@ UpdateJitActivationsForMinorGC(JSRuntime* rt) for (JitActivationIterator activations(cx); !activations.done(); ++activations) { for (OnlyJSJitFrameIter iter(activations); !iter.done(); ++iter) { if (iter.frame().type() == JitFrame_IonJS) - UpdateIonJSFrameForMinorGC(iter.frame()); + UpdateIonJSFrameForMinorGC(rt, iter.frame()); } } } diff --git a/js/src/jit/Linker.cpp b/js/src/jit/Linker.cpp index f38b5e0c1acc..b5f945e74382 100644 --- a/js/src/jit/Linker.cpp +++ b/js/src/jit/Linker.cpp @@ -59,7 +59,7 @@ Linker::newCode(JSContext* cx, CodeKind kind) code->copyFrom(masm); masm.link(code); if (masm.embedsNurseryPointers()) - cx->zone()->group()->storeBuffer().putWholeCell(code); + cx->runtime()->gc.storeBuffer().putWholeCell(code); return code; } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index ddd92551ad25..81d71159fe96 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -962,8 +962,8 @@ jit::IonCompilationCanUseNurseryPointers() // Otherwise, we must be on the active thread during MIR construction. The // store buffer must have been notified that minor GCs must cancel pending // or in progress Ion compilations. - JSContext* cx = TlsContext.get(); - return cx->zone()->group()->storeBuffer().cancelIonCompilations(); + JSRuntime* rt = TlsContext.get()->zone()->runtimeFromActiveCooperatingThread(); + return rt->gc.storeBuffer().cancelIonCompilations(); } #endif // DEBUG diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 4db7be0884a2..d7691108a386 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -579,7 +579,7 @@ NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group) // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. if (!IsInsideNursery(obj)) - cx->zone()->group()->storeBuffer().putWholeCell(obj); + cx->runtime()->gc.storeBuffer().putWholeCell(obj); return obj; } @@ -596,7 +596,7 @@ NewSingletonCallObject(JSContext* cx, HandleShape shape) // the call object tenured, so barrier as needed before re-entering. MOZ_ASSERT(!IsInsideNursery(obj), "singletons are created in the tenured heap"); - cx->zone()->group()->storeBuffer().putWholeCell(obj); + cx->runtime()->gc.storeBuffer().putWholeCell(obj); return obj; } diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp index 9cc9a3f2b8f3..7e6967ca16a6 100644 --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -1062,7 +1062,8 @@ CodeGeneratorShared::verifyCompactTrackedOptimizationsMap(JitCode* code, uint32_ // decoded. This is disabled for now if the types table might // contain nursery pointers, in which case the types might not // match, see bug 1175761. - if (!code->zone()->group()->storeBuffer().cancelIonCompilations()) { + JSRuntime* rt = code->runtimeFromActiveCooperatingThread(); + if (!rt->gc.storeBuffer().cancelIonCompilations()) { IonTrackedOptimizationsTypeInfo typeInfo = typesTable->entry(index); TempOptimizationTypeInfoVector tvec(alloc()); ReadTempTypeInfoVectorOp top(alloc(), &tvec); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 4e8fc9458f2b..a82b34510c12 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -1219,7 +1219,7 @@ void js::DumpHeap(JSContext* cx, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehaviour) { if (nurseryBehaviour == js::CollectNurseryBeforeDump) - EvictAllNurseries(cx->runtime(), JS::gcreason::API); + cx->runtime()->gc.evictNursery(JS::gcreason::API); DumpHeapTracer dtrc(fp, cx); diff --git a/js/src/proxy/CrossCompartmentWrapper.cpp b/js/src/proxy/CrossCompartmentWrapper.cpp index 1b1f5fec5cc5..c0ecc8900d6f 100644 --- a/js/src/proxy/CrossCompartmentWrapper.cpp +++ b/js/src/proxy/CrossCompartmentWrapper.cpp @@ -706,7 +706,7 @@ js::RecomputeWrappers(JSContext* cx, const CompartmentFilter& sourceFilter, continue; if (!evictedNursery && c->hasNurseryAllocatedWrapperEntries(targetFilter)) { - EvictAllNurseries(cx->runtime()); + cx->runtime()->gc.evictNursery(); evictedNursery = true; } diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index 85b911ef57d8..d212ff2c144f 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -868,7 +868,7 @@ ArgumentsObject::objectMoved(JSObject* dst, JSObject* src) if (!IsInsideNursery(src)) return 0; - Nursery& nursery = dst->zone()->group()->nursery(); + Nursery& nursery = dst->runtimeFromActiveCooperatingThread()->gc.nursery(); size_t nbytesTotal = 0; if (!nursery.isInside(nsrc->data())) { diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 1a35ec5e0ab7..7b3a50b485ee 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -1653,7 +1653,7 @@ ArrayBufferViewObject::trace(JSTracer* trc, JSObject* objArg) // not be enough bytes available, and other views might have data // pointers whose forwarding pointers would overlap this one. if (trc->isTenuringTracer()) { - Nursery& nursery = obj->zoneFromAnyThread()->group()->nursery(); + Nursery& nursery = trc->runtime()->gc.nursery(); nursery.maybeSetForwardingPointer(trc, srcData, dstData, /* direct = */ false); } } else { diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp index 058eced2a4de..1e1ba81556af 100644 --- a/js/src/vm/JSObject.cpp +++ b/js/src/vm/JSObject.cpp @@ -1558,13 +1558,13 @@ JSObject::fixDictionaryShapeAfterSwap() } static MOZ_MUST_USE bool -CopyProxyValuesBeforeSwap(ProxyObject* proxy, Vector& values) +CopyProxyValuesBeforeSwap(JSContext* cx, ProxyObject* proxy, Vector& values) { MOZ_ASSERT(values.empty()); // Remove the GCPtrValues we're about to swap from the store buffer, to // ensure we don't trace bogus values. - StoreBuffer& sb = proxy->zone()->group()->storeBuffer(); + StoreBuffer& sb = cx->runtime()->gc.storeBuffer(); // Reserve space for the private slot and the reserved slots. if (!values.reserve(1 + proxy->numReservedSlots())) @@ -1635,8 +1635,8 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b) * nursery pointers in either object. */ MOZ_ASSERT(!IsInsideNursery(a) && !IsInsideNursery(b)); - cx->zone()->group()->storeBuffer().putWholeCell(a); - cx->zone()->group()->storeBuffer().putWholeCell(b); + cx->runtime()->gc.storeBuffer().putWholeCell(a); + cx->runtime()->gc.storeBuffer().putWholeCell(b); unsigned r = NotifyGCPreSwap(a, b); @@ -1722,11 +1722,11 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b) ProxyObject* proxyB = b->is() ? &b->as() : nullptr; if (aIsProxyWithInlineValues) { - if (!CopyProxyValuesBeforeSwap(proxyA, avals)) + if (!CopyProxyValuesBeforeSwap(cx, proxyA, avals)) oomUnsafe.crash("CopyProxyValuesBeforeSwap"); } if (bIsProxyWithInlineValues) { - if (!CopyProxyValuesBeforeSwap(proxyB, bvals)) + if (!CopyProxyValuesBeforeSwap(cx, proxyB, bvals)) oomUnsafe.crash("CopyProxyValuesBeforeSwap"); } @@ -3885,7 +3885,7 @@ JSObject::sizeOfIncludingThisInNursery() const MOZ_ASSERT(!isTenured()); - const Nursery& nursery = zone()->group()->nursery(); + const Nursery& nursery = runtimeFromActiveCooperatingThread()->gc.nursery(); size_t size = Arena::thingSize(allocKindForTenure(nursery)); if (is()) { diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h index c041d6adfcde..18a0c4ef089e 100644 --- a/js/src/vm/NativeObject-inl.h +++ b/js/src/vm/NativeObject-inl.h @@ -124,9 +124,10 @@ NativeObject::elementsRangeWriteBarrierPost(uint32_t start, uint32_t count) for (size_t i = 0; i < count; i++) { const Value& v = elements_[start + i]; if ((v.isObject() || v.isString()) && IsInsideNursery(v.toGCThing())) { - zone()->group()->storeBuffer().putSlot(this, HeapSlot::Element, - unshiftedIndex(start + i), - count - i); + JSRuntime* rt = runtimeFromActiveCooperatingThread(); + rt->gc.storeBuffer().putSlot(this, HeapSlot::Element, + unshiftedIndex(start + i), + count - i); return; } } diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index f4f6a42cdd22..4ceaee213517 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1146,18 +1146,6 @@ SetValueRangeToNull(Value* vec, size_t len) extern const JSSecurityCallbacks NullSecurityCallbacks; -inline Nursery& -ZoneGroup::nursery() -{ - return runtime->gc.nursery(); -} - -inline gc::StoreBuffer& -ZoneGroup::storeBuffer() -{ - return runtime->gc.storeBuffer(); -} - // This callback is set by JS::SetProcessLargeAllocationFailureCallback // and may be null. See comment in jsapi.h. extern mozilla::Atomic OnLargeAllocationFailure; diff --git a/js/src/vm/StringType.cpp b/js/src/vm/StringType.cpp index 8fc3236cd763..46d67584b3c9 100644 --- a/js/src/vm/StringType.cpp +++ b/js/src/vm/StringType.cpp @@ -510,7 +510,7 @@ JSRope::flattenInternal(JSContext* maybecx) left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT; left.d.s.u3.base = (JSLinearString*)this; /* will be true on exit */ BarrierMethods::postBarrier((JSString**)&left.d.s.u3.base, nullptr, this); - Nursery& nursery = zone()->group()->nursery(); + Nursery& nursery = runtimeFromActiveCooperatingThread()->gc.nursery(); if (isTenured() && !left.isTenured()) nursery.removeMallocedBuffer(wholeChars); else if (!isTenured() && left.isTenured()) @@ -526,7 +526,7 @@ JSRope::flattenInternal(JSContext* maybecx) } if (!isTenured()) { - Nursery& nursery = zone()->group()->nursery(); + Nursery& nursery = runtimeFromActiveCooperatingThread()->gc.nursery(); if (!nursery.registerMallocedBuffer(wholeChars)) { js_free(wholeChars); if (maybecx) diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index 3e2b1a5fb14a..c88a4515580b 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -685,8 +685,8 @@ void ConstraintTypeSet::postWriteBarrier(JSContext* cx, Type type) { if (type.isSingletonUnchecked() && IsInsideNursery(type.singletonNoBarrier())) { - cx->zone()->group()->storeBuffer().putGeneric(TypeSetRef(cx->zone(), this)); - cx->zone()->group()->storeBuffer().setShouldCancelIonCompilations(); + cx->runtime()->gc.storeBuffer().putGeneric(TypeSetRef(cx->zone(), this)); + cx->runtime()->gc.storeBuffer().setShouldCancelIonCompilations(); } } diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index b296e879cbb4..9edd37f41a77 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -196,7 +196,7 @@ TypedArrayObject::objectMoved(JSObject* obj, JSObject* old) return 0; } - Nursery& nursery = obj->zone()->group()->nursery(); + Nursery& nursery = obj->runtimeFromActiveCooperatingThread()->gc.nursery(); void* buf = oldObj->elements(); if (!nursery.isInside(buf)) { @@ -494,7 +494,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject MOZ_ASSERT(buffer->byteLength() == 0 && (uintptr_t(ptr.unwrapValue()) & gc::ChunkMask) == 0); } else { - cx->zone()->group()->storeBuffer().putWholeCell(obj); + cx->runtime()->gc.storeBuffer().putWholeCell(obj); } } } else { diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h index 736a0a300b6d..ccba79dbf4e6 100644 --- a/js/src/vm/UnboxedObject-inl.h +++ b/js/src/vm/UnboxedObject-inl.h @@ -47,54 +47,6 @@ GetUnboxedValue(uint8_t* p, JSValueType type, bool maybeUninitialized) } } -static inline void -SetUnboxedValueNoTypeChange(JSObject* unboxedObject, - uint8_t* p, JSValueType type, const Value& v, - bool preBarrier) -{ - switch (type) { - case JSVAL_TYPE_BOOLEAN: - *p = v.toBoolean(); - return; - - case JSVAL_TYPE_INT32: - *reinterpret_cast(p) = v.toInt32(); - return; - - case JSVAL_TYPE_DOUBLE: - *reinterpret_cast(p) = v.toNumber(); - return; - - case JSVAL_TYPE_STRING: { - MOZ_ASSERT(!IsInsideNursery(v.toString())); - JSString** np = reinterpret_cast(p); - if (preBarrier) - JSString::writeBarrierPre(*np); - *np = v.toString(); - return; - } - - case JSVAL_TYPE_OBJECT: { - JSObject** np = reinterpret_cast(p); - - // Manually trigger post barriers on the whole object. If we treat - // the pointer as a HeapPtrObject we will get confused later if the - // object is converted to its native representation. - JSObject* obj = v.toObjectOrNull(); - if (IsInsideNursery(obj) && !IsInsideNursery(unboxedObject)) - unboxedObject->zone()->group()->storeBuffer().putWholeCell(unboxedObject); - - if (preBarrier) - JSObject::writeBarrierPre(*np); - *np = obj; - return; - } - - default: - MOZ_CRASH("Invalid type for unboxed value"); - } -} - static inline bool SetUnboxedValue(JSContext* cx, JSObject* unboxedObject, jsid id, uint8_t* p, JSValueType type, const Value& v, bool preBarrier) @@ -125,7 +77,7 @@ SetUnboxedValue(JSContext* cx, JSObject* unboxedObject, jsid id, if (v.isString()) { JSString** np = reinterpret_cast(p); if (IsInsideNursery(v.toString()) && !IsInsideNursery(unboxedObject)) - unboxedObject->zone()->group()->storeBuffer().putWholeCell(unboxedObject); + v.toString()->storeBuffer()->putWholeCell(unboxedObject); if (preBarrier) JSString::writeBarrierPre(*np); @@ -145,8 +97,8 @@ SetUnboxedValue(JSContext* cx, JSObject* unboxedObject, jsid id, // As above, trigger post barriers on the whole object. JSObject* obj = v.toObjectOrNull(); - if (IsInsideNursery(v.toObjectOrNull()) && !IsInsideNursery(unboxedObject)) - unboxedObject->zone()->group()->storeBuffer().putWholeCell(unboxedObject); + if (IsInsideNursery(obj) && !IsInsideNursery(unboxedObject)) + obj->storeBuffer()->putWholeCell(unboxedObject); if (preBarrier) JSObject::writeBarrierPre(*np); diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index ca78c99cf98d..e0559219158b 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -384,7 +384,7 @@ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle obj // convert the object to its native representation, we will end up with a // corrupted store buffer entry. if (IsInsideNursery(expando) && !IsInsideNursery(obj)) - cx->zone()->group()->storeBuffer().putWholeCell(obj); + expando->storeBuffer()->putWholeCell(obj); obj->setExpandoUnsafe(expando); return expando; @@ -599,7 +599,7 @@ UnboxedPlainObject::convertToNative(JSContext* cx, JSObject* obj) // writes to the expando (see WholeCellEdges::trace), so after conversion // we need to make sure the expando itself will still be traced. if (expando && !IsInsideNursery(expando)) - cx->zone()->group()->storeBuffer().putWholeCell(expando); + cx->runtime()->gc.storeBuffer().putWholeCell(expando); obj->setGroup(layout.nativeGroup()); obj->as().setLastPropertyMakeNative(cx, layout.nativeShape());