diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 9dcb2a043493..3a393623caab 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -1468,7 +1468,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)) - runtimeFromMainThread()->gc.storeBuffer.putWholeCellFromMainThread(this); + runtimeFromMainThread()->gc.storeBuffer.putWholeCell(this); } /*static*/ OutlineTypedObject* @@ -2224,7 +2224,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. - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(buffer); + cx->runtime()->gc.storeBuffer.putWholeCell(buffer); } return buffer; diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index f80a918e4465..edd3e5dbfeec 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -279,12 +279,12 @@ struct InternalGCMethods sb->assertHasValueEdge(vp); return; } - sb->putValueFromAnyThread(vp); + sb->putValue(vp); return; } // Remove the prev entry if the new value does not need it. if (prev.isObject() && (sb = reinterpret_cast(&prev.toObject())->storeBuffer())) - sb->unputValueFromAnyThread(vp); + sb->unputValue(vp); } static void readBarrier(const Value& v) { @@ -598,7 +598,7 @@ class HeapSlot : public BarrieredBase if (this->value.isObject()) { gc::Cell* cell = reinterpret_cast(&this->value.toObject()); if (cell->storeBuffer()) - cell->storeBuffer()->putSlotFromAnyThread(owner, kind, slot, 1); + cell->storeBuffer()->putSlot(owner, kind, slot, 1); } } }; diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 00353c068e77..d52dbdd574b1 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -344,48 +344,22 @@ class StoreBuffer void* data; }; - bool isOkayToUseBuffer() const { + template + void unput(Buffer& buffer, const Edge& edge) { MOZ_ASSERT(!JS::shadow::Runtime::asShadowRuntime(runtime_)->isHeapBusy()); - - /* - * Disabled store buffers may not have a valid state; e.g. when stored - * inline in the ChunkTrailer. - */ + MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_)); if (!isEnabled()) - return false; - - /* - * The concurrent parsing thread cannot validly insert into the buffer, - * but it should not activate the re-entrancy guard either. - */ - if (!CurrentThreadCanAccessRuntime(runtime_)) - return false; - - return true; - } - - template - void putFromAnyThread(Buffer& buffer, const Edge& edge) { - if (!isOkayToUseBuffer()) - return; - mozilla::ReentrancyGuard g(*this); - if (edge.maybeInRememberedSet(nursery_)) - buffer.put(this, edge); - } - - template - void unputFromAnyThread(Buffer& buffer, const Edge& edge) { - if (!isOkayToUseBuffer()) return; mozilla::ReentrancyGuard g(*this); buffer.unput(this, edge); } template - void putFromMainThread(Buffer& buffer, const Edge& edge) { + void put(Buffer& buffer, const Edge& edge) { + MOZ_ASSERT(!JS::shadow::Runtime::asShadowRuntime(runtime_)->isHeapBusy()); + MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_)); if (!isEnabled()) return; - MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_)); mozilla::ReentrancyGuard g(*this); if (edge.maybeInRememberedSet(nursery_)) buffer.put(this, edge); @@ -425,26 +399,26 @@ class StoreBuffer bool cancelIonCompilations() const { return cancelIonCompilations_; } /* Insert a single edge into the buffer/remembered set. */ - void putValueFromAnyThread(JS::Value* vp) { putFromAnyThread(bufferVal, ValueEdge(vp)); } - void unputValueFromAnyThread(JS::Value* vp) { unputFromAnyThread(bufferVal, ValueEdge(vp)); } - void putCellFromAnyThread(Cell** cellp) { putFromAnyThread(bufferCell, CellPtrEdge(cellp)); } - void unputCellFromAnyThread(Cell** cellp) { unputFromAnyThread(bufferCell, CellPtrEdge(cellp)); } - void putSlotFromAnyThread(NativeObject* obj, int kind, int32_t start, int32_t count) { - putFromAnyThread(bufferSlot, SlotsEdge(obj, kind, start, count)); + void putValue(JS::Value* vp) { put(bufferVal, ValueEdge(vp)); } + void unputValue(JS::Value* vp) { unput(bufferVal, ValueEdge(vp)); } + void putCell(Cell** cellp) { put(bufferCell, CellPtrEdge(cellp)); } + void unputCell(Cell** cellp) { unput(bufferCell, CellPtrEdge(cellp)); } + void putSlot(NativeObject* obj, int kind, int32_t start, int32_t count) { + put(bufferSlot, SlotsEdge(obj, kind, start, count)); } - void putWholeCellFromMainThread(Cell* cell) { + void putWholeCell(Cell* cell) { MOZ_ASSERT(cell->isTenured()); - putFromMainThread(bufferWholeCell, WholeCellEdges(cell)); + put(bufferWholeCell, WholeCellEdges(cell)); } /* Insert an entry into the generic buffer. */ template - void putGeneric(const T& t) { putFromAnyThread(bufferGeneric, t);} + void putGeneric(const T& t) { put(bufferGeneric, t);} /* Insert or update a callback entry. */ template void putCallback(void (*callback)(JSTracer* trc, Key* key, void* data), Key* key, void* data) { - putFromAnyThread(bufferGeneric, CallbackRef(callback, key, data)); + put(bufferGeneric, CallbackRef(callback, key, data)); } void assertHasValueEdge(JS::Value* vp) { diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index b4e80fd15a3f..2e167d0aa3d0 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -8208,7 +8208,7 @@ CodeGenerator::link(JSContext* cx, CompilerConstraintList* constraints) for (size_t i = 0; i < graph.numConstants(); i++) { const Value& v = vp[i]; if (v.isObject() && IsInsideNursery(&v.toObject())) { - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(script); + cx->runtime()->gc.storeBuffer.putWholeCell(script); break; } } diff --git a/js/src/jit/Linker.h b/js/src/jit/Linker.h index 340b98e3dd7f..4575d2e31f4c 100644 --- a/js/src/jit/Linker.h +++ b/js/src/jit/Linker.h @@ -72,7 +72,7 @@ class Linker code->copyFrom(masm); masm.link(code); if (masm.embedsNurseryPointers()) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code); + cx->runtime()->gc.storeBuffer.putWholeCell(code); return code; } }; diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 9799313ac7b6..070794fc448f 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -495,7 +495,7 @@ NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group, uint32_ // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. if (!IsInsideNursery(obj)) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); + cx->runtime()->gc.storeBuffer.putWholeCell(obj); return obj; } @@ -512,7 +512,7 @@ NewSingletonCallObject(JSContext* cx, HandleShape shape, uint32_t lexicalBegin) // the call object tenured, so barrier as needed before re-entering. MOZ_ASSERT(!IsInsideNursery(obj), "singletons are created in the tenured heap"); - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); + cx->runtime()->gc.storeBuffer.putWholeCell(obj); return obj; } @@ -613,7 +613,7 @@ void PostWriteBarrier(JSRuntime* rt, JSObject* obj) { MOZ_ASSERT(!IsInsideNursery(obj)); - rt->gc.storeBuffer.putWholeCellFromMainThread(obj); + rt->gc.storeBuffer.putWholeCell(obj); } void diff --git a/js/src/jit/arm64/Assembler-arm64.cpp b/js/src/jit/arm64/Assembler-arm64.cpp index fdeb72df5406..c9fa1d639889 100644 --- a/js/src/jit/arm64/Assembler-arm64.cpp +++ b/js/src/jit/arm64/Assembler-arm64.cpp @@ -563,7 +563,7 @@ Assembler::FixupNurseryObjects(JSContext* cx, JitCode* code, CompactBufferReader } if (hasNurseryPointers) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(code); + cx->runtime()->gc.storeBuffer.putWholeCell(code); } int32_t diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 6843d0cc15f6..57cba2a81f6b 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1569,8 +1569,8 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b) * nursery pointers in either object. */ MOZ_ASSERT(!IsInsideNursery(a) && !IsInsideNursery(b)); - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(a); - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(b); + cx->runtime()->gc.storeBuffer.putWholeCell(a); + cx->runtime()->gc.storeBuffer.putWholeCell(b); unsigned r = NotifyGCPreSwap(a, b); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 6a90b6533416..490c1fb2b152 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -647,13 +647,13 @@ JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next) // via a different store buffer. if (prev && prev->storeBuffer()) return; - buffer->putCellFromAnyThread(static_cast(cellp)); + buffer->putCell(static_cast(cellp)); return; } // Remove the prev entry if the new value does not need it. if (prev && (buffer = prev->storeBuffer())) - buffer->unputCellFromAnyThread(static_cast(cellp)); + buffer->unputCell(static_cast(cellp)); } namespace js { diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h index 413eca556310..6d263b561d18 100644 --- a/js/src/vm/NativeObject.h +++ b/js/src/vm/NativeObject.h @@ -945,8 +945,8 @@ class NativeObject : public JSObject const Value& v = elements_[start + i]; if (v.isObject() && IsInsideNursery(&v.toObject())) { JS::shadow::Runtime* shadowRuntime = shadowRuntimeFromMainThread(); - shadowRuntime->gcStoreBufferPtr()->putSlotFromAnyThread(this, HeapSlot::Element, - start + i, count - i); + shadowRuntime->gcStoreBufferPtr()->putSlot(this, HeapSlot::Element, + start + i, count - i); return; } } @@ -1161,7 +1161,7 @@ class NativeObject : public JSObject MOZ_ASSERT(*cellp); gc::StoreBuffer* storeBuffer = (*cellp)->storeBuffer(); if (storeBuffer) - storeBuffer->putCellFromAnyThread(cellp); + storeBuffer->putCell(cellp); } /* Private data accessors. */ diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 8642ce49ab3b..e92750b42eb6 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -362,7 +362,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject // may be in the nursery, so include a barrier to make sure this // object is updated if that typed object moves. if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(buffer->dataPointer())) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); + cx->runtime()->gc.storeBuffer.putWholeCell(obj); } else { void* data = obj->fixedData(FIXED_DATA_START); obj->initPrivate(data); @@ -1011,7 +1011,7 @@ DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength, // Include a barrier if the data view's data pointer is in the nursery, as // is done for typed arrays. if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(arrayBuffer->dataPointer())) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); + cx->runtime()->gc.storeBuffer.putWholeCell(obj); // Verify that the private slot is at the expected place MOZ_ASSERT(dvobj.numFixedSlots() == TypedArrayLayout::DATA_SLOT); diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h index b0a5bf61b4d5..10e120034471 100644 --- a/js/src/vm/UnboxedObject-inl.h +++ b/js/src/vm/UnboxedObject-inl.h @@ -82,7 +82,7 @@ SetUnboxedValueNoTypeChange(JSObject* unboxedObject, JSObject* obj = v.toObjectOrNull(); if (IsInsideNursery(obj) && !IsInsideNursery(unboxedObject)) { JSRuntime* rt = unboxedObject->runtimeFromMainThread(); - rt->gc.storeBuffer.putWholeCellFromMainThread(unboxedObject); + rt->gc.storeBuffer.putWholeCell(unboxedObject); } if (preBarrier) @@ -146,7 +146,7 @@ SetUnboxedValue(ExclusiveContext* cx, JSObject* unboxedObject, jsid id, JSObject* obj = v.toObjectOrNull(); if (IsInsideNursery(v.toObjectOrNull()) && !IsInsideNursery(unboxedObject)) { JSRuntime* rt = unboxedObject->runtimeFromMainThread(); - rt->gc.storeBuffer.putWholeCellFromMainThread(unboxedObject); + rt->gc.storeBuffer.putWholeCell(unboxedObject); } if (preBarrier) @@ -619,7 +619,7 @@ CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src, // Add a store buffer entry if we might have copied a nursery pointer to dst. if (UnboxedTypeNeedsPostBarrier(DstType) && !IsInsideNursery(dst)) - dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCellFromMainThread(dst); + dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCell(dst); } else if (DstType == JSVAL_TYPE_DOUBLE && SrcType == JSVAL_TYPE_INT32) { uint8_t* dstData = dst->as().elements(); uint8_t* srcData = src->as().elements(); diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 1b9c97e79e4b..279a67472d0b 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -354,7 +354,7 @@ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle obj // the object to its native representation, we will end up with a corrupted // store buffer entry. if (IsInsideNursery(expando) && !IsInsideNursery(obj)) - cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); + cx->runtime()->gc.storeBuffer.putWholeCell(obj); obj->expando_ = expando; return expando; @@ -575,7 +575,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->runtime()->gc.storeBuffer.putWholeCellFromMainThread(expando); + cx->runtime()->gc.storeBuffer.putWholeCell(expando); obj->setGroup(layout.nativeGroup()); obj->as().setLastPropertyMakeNative(cx, layout.nativeShape());