mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 14:58:37 +09:00
903519 - Implement AutoSuppressNurseryCellAlloc to avoid nursery allocation just before offthread parse startup
903519 - Implement AutoSuppressNurseryCellAlloc to avoid nursery allocation just before offthread parse startup
This commit is contained in:
parent
eb8b8e28d2
commit
6079c8fdb4
4 changed files with 64 additions and 12 deletions
|
|
@ -39,8 +39,9 @@ js::Allocate(ExclusiveContext* cx, AllocKind kind, size_t nDynamicSlots, Initial
|
|||
|
||||
MOZ_ASSERT_IF(nDynamicSlots != 0, clasp->isNative() || clasp->isProxy());
|
||||
|
||||
// Off-main-thread alloc cannot trigger GC or make runtime assertions.
|
||||
if (!cx->isJSContext()) {
|
||||
// We cannot trigger GC or make runtime assertions when nursery allocation
|
||||
// is suppressed, either explicitly or because we are off-thread.
|
||||
if (cx->isNurseryAllocSuppressed()) {
|
||||
JSObject* obj = GCRuntime::tryNewTenuredObject<NoGC>(cx, kind, thingSize, nDynamicSlots);
|
||||
if (MOZ_UNLIKELY(allowGC && !obj))
|
||||
ReportOutOfMemory(cx);
|
||||
|
|
@ -81,8 +82,9 @@ template <AllowGC allowGC>
|
|||
JSObject*
|
||||
GCRuntime::tryNewNurseryObject(JSContext* cx, size_t thingSize, size_t nDynamicSlots, const Class* clasp)
|
||||
{
|
||||
MOZ_ASSERT(isNurseryAllocAllowed());
|
||||
MOZ_ASSERT(!cx->zone()->usedByExclusiveThread);
|
||||
MOZ_ASSERT(cx->isNurseryAllocAllowed());
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
|
||||
MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
|
||||
JSObject* obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
|
||||
if (obj)
|
||||
|
|
@ -133,7 +135,8 @@ GCRuntime::tryNewNurseryString(JSContext* cx, size_t thingSize, AllocKind kind)
|
|||
{
|
||||
MOZ_ASSERT(IsNurseryAllocable(kind));
|
||||
MOZ_ASSERT(cx->isNurseryAllocAllowed());
|
||||
MOZ_ASSERT(!cx->isJSContext());
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
|
||||
MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
|
||||
|
||||
Cell* cell = cx->nursery().allocateString(cx, cx->zone(), thingSize, kind);
|
||||
|
|
@ -162,7 +165,7 @@ js::AllocateString(JSContext* cx, InitialHeap heap)
|
|||
MOZ_ASSERT(size == sizeof(JSString) || size == sizeof(JSFatInlineString));
|
||||
|
||||
// Off-thread alloc cannot trigger GC or make runtime assertions.
|
||||
if (cx->isJSContext()) {
|
||||
if (cx->isNurseryAllocSuppressed()) {
|
||||
StringAllocT* str = GCRuntime::tryNewTenuredThing<StringAllocT, NoGC>(cx, kind, size);
|
||||
if (MOZ_UNLIKELY(allowGC && !str))
|
||||
ReportOutOfMemory(cx);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ class JitContext;
|
|||
class DebugModeOSRVolatileJitFrameIterator;
|
||||
} // namespace jit
|
||||
|
||||
namespace gc {
|
||||
class AutoSuppressNurseryCellAlloc;
|
||||
}
|
||||
|
||||
typedef HashSet<Shape*> ShapeSet;
|
||||
|
||||
/* Detects cycles when traversing an object graph. */
|
||||
|
|
@ -113,8 +117,34 @@ enum class ContextKind
|
|||
// JSRuntime, so it's more efficient to use the base class.
|
||||
JSRuntime* const runtime_;
|
||||
|
||||
// The thread on which this context is running, if this is not a JSContext.
|
||||
HelperThread* helperThread_;
|
||||
/*
|
||||
* A JSContext encapsulates the thread local state used when using the JS
|
||||
* runtime.
|
||||
*/
|
||||
struct JSContext : public JS::RootingContext,
|
||||
public js::MallocProvider<JSContext>
|
||||
{
|
||||
JSContext(JSRuntime* runtime, const JS::ContextOptions& options);
|
||||
~JSContext();
|
||||
|
||||
bool init(js::ContextKind kind);
|
||||
|
||||
private:
|
||||
js::UnprotectedData<JSRuntime*> runtime_;
|
||||
js::WriteOnceData<js::ContextKind> kind_;
|
||||
|
||||
// System handle for the thread this context is associated with.
|
||||
js::WriteOnceData<size_t> threadNative_;
|
||||
|
||||
// The thread on which this context is running, if this is performing a parse task.
|
||||
js::ThreadLocalData<js::HelperThread*> helperThread_;
|
||||
|
||||
friend class js::gc::AutoSuppressNurseryCellAlloc;
|
||||
js::ThreadLocalData<size_t> nurserySuppressions_;
|
||||
|
||||
js::ThreadLocalData<JS::ContextOptions> options_;
|
||||
|
||||
js::ThreadLocalData<js::gc::ArenaLists*> arenas_;
|
||||
|
||||
public:
|
||||
enum ContextKind {
|
||||
|
|
@ -286,8 +316,14 @@ enum class ContextKind
|
|||
void setHelperThread(HelperThread* helperThread);
|
||||
HelperThread* helperThread() const { return helperThread_; }
|
||||
|
||||
// Threads with an ExclusiveContext may freely access any data in their
|
||||
// compartment and zone.
|
||||
void setHelperThread(js::HelperThread* helperThread);
|
||||
js::HelperThread* helperThread() const { return helperThread_; }
|
||||
|
||||
bool isNurseryAllocSuppressed() const {
|
||||
return nurserySuppressions_;
|
||||
}
|
||||
|
||||
// Threads may freely access any data in their compartment and zone.
|
||||
JSCompartment* compartment() const {
|
||||
return compartment_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,7 +643,7 @@ StartOffThreadParseTask(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
// Suppress GC so that calls below do not trigger a new incremental GC
|
||||
// which could require barriers on the atoms compartment.
|
||||
gc::AutoSuppressGC nogc(cx);
|
||||
gc::AutoAssertNoNurseryAlloc noNurseryAlloc(cx->runtime());
|
||||
gc::AutoSuppressNurseryCellAlloc noNurseryAlloc(cx);
|
||||
AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
|
||||
|
||||
Maybe<AutoClearUsedByHelperThread> clearUseGuard;
|
||||
|
|
@ -1931,6 +1931,18 @@ HelperThread::handleGCHelperWorkload(AutoLockHelperThreadState& locked)
|
|||
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
||||
}
|
||||
|
||||
void
|
||||
JSContext::setHelperThread(HelperThread* thread)
|
||||
{
|
||||
if (helperThread_)
|
||||
nurserySuppressions_--;
|
||||
|
||||
helperThread_ = thread;
|
||||
|
||||
if (helperThread_)
|
||||
nurserySuppressions_++;
|
||||
}
|
||||
|
||||
void
|
||||
HelperThread::threadLoop()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "jscntxtinlines.h"
|
||||
#include "jscompartmentinlines.h"
|
||||
|
||||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::IsSame;
|
||||
|
|
@ -636,7 +637,7 @@ js::ConcatStrings(ExclusiveContext* cx,
|
|||
bool canUseInline = isLatin1
|
||||
? JSInlineString::lengthFits<Latin1Char>(wholeLength)
|
||||
: JSInlineString::lengthFits<char16_t>(wholeLength);
|
||||
if (canUseInline && cx->isJSContext()) {
|
||||
if (canUseInline) {
|
||||
Latin1Char* latin1Buf = nullptr; // initialize to silence GCC warning
|
||||
char16_t* twoByteBuf = nullptr; // initialize to silence GCC warning
|
||||
JSInlineString* str = isLatin1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue