зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1337112 - Remove links from JSRuntime to its single context and zone group, r=jandem,jonco.
--HG-- extra : rebase_source : ebf319af724d5f829cdf5c2386dc82d49be89989
This commit is contained in:
Родитель
e1b82a23c1
Коммит
01a649c197
|
@ -1655,7 +1655,7 @@ nsMessageManagerScriptExecutor::InitChildGlobalInternal(
|
|||
const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES;
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::SystemZone);
|
||||
options.creationOptions().setSystemZone();
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
|
||||
if (xpc::SharedMemoryEnabled()) {
|
||||
|
|
|
@ -2736,7 +2736,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (top && top->GetGlobalJSObject()) {
|
||||
options.creationOptions().setSameZoneAs(top->GetGlobalJSObject());
|
||||
options.creationOptions().setExistingZone(top->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
options.creationOptions().setSecureContext(aIsSecureContext);
|
||||
|
|
|
@ -110,7 +110,7 @@ SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto)
|
|||
// lots of zones for what are probably very short-lived
|
||||
// compartments. This should help them be GCed quicker and take up
|
||||
// less memory before they're GCed.
|
||||
.setZone(JS::SystemZone);
|
||||
.setSystemZone();
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
|
||||
|
|
|
@ -1075,10 +1075,10 @@ public:
|
|||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
|
||||
nsresult Initialize(JSContext* aParentContext)
|
||||
nsresult Initialize(JSRuntime* aParentRuntime)
|
||||
{
|
||||
nsresult rv =
|
||||
CycleCollectedJSContext::Initialize(aParentContext,
|
||||
CycleCollectedJSContext::Initialize(aParentRuntime,
|
||||
WORKER_DEFAULT_RUNTIME_HEAPSIZE,
|
||||
WORKER_DEFAULT_NURSERY_SIZE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -1187,7 +1187,7 @@ class WorkerThreadPrimaryRunnable final : public Runnable
|
|||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
RefPtr<WorkerThread> mThread;
|
||||
JSContext* mParentContext;
|
||||
JSRuntime* mParentRuntime;
|
||||
|
||||
class FinishedRunnable final : public Runnable
|
||||
{
|
||||
|
@ -1213,8 +1213,8 @@ class WorkerThreadPrimaryRunnable final : public Runnable
|
|||
public:
|
||||
WorkerThreadPrimaryRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
WorkerThread* aThread,
|
||||
JSContext* aParentContext)
|
||||
: mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentContext(aParentContext)
|
||||
JSRuntime* aParentRuntime)
|
||||
: mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentRuntime(aParentRuntime)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
MOZ_ASSERT(aThread);
|
||||
|
@ -1893,7 +1893,7 @@ RuntimeService::ScheduleWorker(WorkerPrivate* aWorkerPrivate)
|
|||
JSContext* cx = CycleCollectedJSContext::Get()->Context();
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new WorkerThreadPrimaryRunnable(aWorkerPrivate, thread,
|
||||
JS_GetParentContext(cx));
|
||||
JS_GetParentRuntime(cx));
|
||||
if (NS_FAILED(thread->DispatchPrimaryRunnable(friendKey, runnable.forget()))) {
|
||||
UnregisterWorker(aWorkerPrivate);
|
||||
return false;
|
||||
|
@ -2861,7 +2861,7 @@ WorkerThreadPrimaryRunnable::Run()
|
|||
nsCycleCollector_startup();
|
||||
|
||||
WorkerJSContext context(mWorkerPrivate);
|
||||
nsresult rv = context.Initialize(mParentContext);
|
||||
nsresult rv = context.Initialize(mParentRuntime);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -451,7 +451,7 @@ XPCShellEnvironment::Init()
|
|||
}
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::SystemZone);
|
||||
options.creationOptions().setSystemZone();
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
if (xpc::SharedMemoryEnabled())
|
||||
options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
|
||||
|
|
|
@ -347,6 +347,7 @@ MinorGC(JSContext* cx, unsigned argc, Value* vp)
|
|||
#define FOR_EACH_GC_PARAM(_) \
|
||||
_("maxBytes", JSGC_MAX_BYTES, true) \
|
||||
_("maxMallocBytes", JSGC_MAX_MALLOC_BYTES, true) \
|
||||
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
|
||||
_("gcBytes", JSGC_BYTES, false) \
|
||||
_("gcNumber", JSGC_NUMBER, false) \
|
||||
_("mode", JSGC_MODE, true) \
|
||||
|
@ -421,9 +422,16 @@ GCParameter(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (disableOOMFunctions && (param == JSGC_MAX_BYTES || param == JSGC_MAX_MALLOC_BYTES)) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
if (disableOOMFunctions) {
|
||||
switch (param) {
|
||||
case JSGC_MAX_BYTES:
|
||||
case JSGC_MAX_MALLOC_BYTES:
|
||||
case JSGC_MAX_NURSERY_BYTES:
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double d;
|
||||
|
|
|
@ -980,8 +980,9 @@ class GCRuntime
|
|||
public:
|
||||
JSRuntime* const rt;
|
||||
|
||||
/* Embedders can use this zone however they wish. */
|
||||
/* Embedders can use this zone and group however they wish. */
|
||||
UnprotectedData<JS::Zone*> systemZone;
|
||||
UnprotectedData<ZoneGroup*> systemZoneGroup;
|
||||
|
||||
// List of all zone groups (protected by the GC lock).
|
||||
ActiveThreadOrGCTaskData<ZoneGroupVector> groups;
|
||||
|
|
|
@ -553,7 +553,6 @@ void
|
|||
js::Nursery::collect(JS::gcreason::Reason reason)
|
||||
{
|
||||
MOZ_ASSERT(!TlsContext.get()->suppressGC);
|
||||
MOZ_RELEASE_ASSERT(zoneGroup()->ownedByCurrentThread());
|
||||
|
||||
if (!isEnabled() || isEmpty()) {
|
||||
// Our barriers are not always exact, and there may be entries in the
|
||||
|
|
|
@ -562,10 +562,6 @@ struct Zone : public JS::shadow::Zone,
|
|||
source->uniqueIds().clear();
|
||||
}
|
||||
|
||||
JSContext* contextFromMainThread() {
|
||||
return runtime_->contextFromMainThread();
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
// Assert that the UniqueId table has been redirected successfully.
|
||||
void checkUniqueIdTableAfterMovingGC();
|
||||
|
|
|
@ -48,6 +48,9 @@ ZoneGroup::init(size_t maxNurseryBytes)
|
|||
ZoneGroup::~ZoneGroup()
|
||||
{
|
||||
js_delete(jitZoneGroup.ref());
|
||||
|
||||
if (this == runtime->gc.systemZoneGroup)
|
||||
runtime->gc.systemZoneGroup = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -60,6 +63,8 @@ ZoneGroup::enter()
|
|||
MOZ_ASSERT(ownerContext().context() == nullptr);
|
||||
MOZ_ASSERT(enterCount == 0);
|
||||
ownerContext_ = CooperatingContext(cx);
|
||||
if (cx->generationalDisabled)
|
||||
nursery().disable();
|
||||
}
|
||||
enterCount++;
|
||||
}
|
||||
|
|
|
@ -130,42 +130,6 @@ class ZoneGroup
|
|||
mozilla::LinkedList<js::Debugger>& debuggerList() { return debuggerList_.ref(); }
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoAccessZoneGroup
|
||||
{
|
||||
ZoneGroup* group;
|
||||
|
||||
public:
|
||||
explicit AutoAccessZoneGroup(ZoneGroup* group)
|
||||
: group(group)
|
||||
{
|
||||
group->enter();
|
||||
}
|
||||
|
||||
~AutoAccessZoneGroup() {
|
||||
group->leave();
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoAccessZoneGroups
|
||||
{
|
||||
Vector<ZoneGroup*, 4, SystemAllocPolicy> acquiredGroups;
|
||||
|
||||
public:
|
||||
AutoAccessZoneGroups() {}
|
||||
|
||||
~AutoAccessZoneGroups() {
|
||||
for (size_t i = 0; i < acquiredGroups.length(); i++)
|
||||
acquiredGroups[i]->leave();
|
||||
}
|
||||
|
||||
void access(ZoneGroup* group) {
|
||||
group->enter();
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
if (!acquiredGroups.append(group))
|
||||
oomUnsafe.crash("acquiredGroups.append failed");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // gc_Zone_h
|
||||
|
|
|
@ -463,18 +463,14 @@ JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
|
|||
#endif
|
||||
|
||||
JS_PUBLIC_API(JSContext*)
|
||||
JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSContext* parentContext)
|
||||
JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
|
||||
{
|
||||
MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running,
|
||||
"must call JS_Init prior to creating any JSContexts");
|
||||
|
||||
// Make sure that all parent runtimes are the topmost parent.
|
||||
JSRuntime* parentRuntime = nullptr;
|
||||
if (parentContext) {
|
||||
parentRuntime = parentContext->runtime();
|
||||
while (parentRuntime && parentRuntime->parentRuntime)
|
||||
parentRuntime = parentRuntime->parentRuntime;
|
||||
}
|
||||
while (parentRuntime && parentRuntime->parentRuntime)
|
||||
parentRuntime = parentRuntime->parentRuntime;
|
||||
|
||||
return NewContext(maxbytes, maxNurseryBytes, parentRuntime);
|
||||
}
|
||||
|
@ -546,10 +542,10 @@ JS_EndRequest(JSContext* cx)
|
|||
StopRequest(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSContext*)
|
||||
JS_GetParentContext(JSContext* cx)
|
||||
JS_PUBLIC_API(JSRuntime*)
|
||||
JS_GetParentRuntime(JSContext* cx)
|
||||
{
|
||||
return cx->runtime()->parentRuntime ? cx->runtime()->parentRuntime->unsafeContextFromAnyThread() : cx;
|
||||
return cx->runtime()->parentRuntime ? cx->runtime()->parentRuntime : cx->runtime();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSVersion)
|
||||
|
@ -1743,16 +1739,42 @@ JS::CompartmentBehaviors::extraWarnings(JSContext* cx) const
|
|||
}
|
||||
|
||||
JS::CompartmentCreationOptions&
|
||||
JS::CompartmentCreationOptions::setZone(ZoneSpecifier spec)
|
||||
JS::CompartmentCreationOptions::setSystemZone()
|
||||
{
|
||||
zone_.spec = spec;
|
||||
zoneSpec_ = JS::SystemZone;
|
||||
zonePointer_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JS::CompartmentCreationOptions&
|
||||
JS::CompartmentCreationOptions::setSameZoneAs(JSObject* obj)
|
||||
JS::CompartmentCreationOptions::setExistingZone(JSObject* obj)
|
||||
{
|
||||
zone_.pointer = static_cast<void*>(obj->zone());
|
||||
zoneSpec_ = JS::ExistingZone;
|
||||
zonePointer_ = obj->zone();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JS::CompartmentCreationOptions&
|
||||
JS::CompartmentCreationOptions::setNewZoneInNewZoneGroup()
|
||||
{
|
||||
zoneSpec_ = JS::NewZoneInNewZoneGroup;
|
||||
zonePointer_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JS::CompartmentCreationOptions&
|
||||
JS::CompartmentCreationOptions::setNewZoneInSystemZoneGroup()
|
||||
{
|
||||
zoneSpec_ = JS::NewZoneInSystemZoneGroup;
|
||||
zonePointer_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JS::CompartmentCreationOptions&
|
||||
JS::CompartmentCreationOptions::setNewZoneInExistingZoneGroup(JSObject* obj)
|
||||
{
|
||||
zoneSpec_ = JS::NewZoneInExistingZoneGroup;
|
||||
zonePointer_ = obj->zone()->group();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -981,7 +981,7 @@ JS_IsBuiltinFunctionConstructor(JSFunction* fun);
|
|||
extern JS_PUBLIC_API(JSContext*)
|
||||
JS_NewContext(uint32_t maxbytes,
|
||||
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
|
||||
JSContext* parentContext = nullptr);
|
||||
JSRuntime* parentRuntime = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DestroyContext(JSContext* cx);
|
||||
|
@ -992,8 +992,8 @@ JS_GetContextPrivate(JSContext* cx);
|
|||
JS_PUBLIC_API(void)
|
||||
JS_SetContextPrivate(JSContext* cx, void* data);
|
||||
|
||||
extern JS_PUBLIC_API(JSContext*)
|
||||
JS_GetParentContext(JSContext* cx);
|
||||
extern JS_PUBLIC_API(JSRuntime*)
|
||||
JS_GetParentRuntime(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_BeginRequest(JSContext* cx);
|
||||
|
@ -1710,6 +1710,9 @@ typedef enum JSGCParamKey {
|
|||
/** Number of JS_malloc bytes before last ditch GC. */
|
||||
JSGC_MAX_MALLOC_BYTES = 1,
|
||||
|
||||
/** Maximum size of the generational GC nurseries. */
|
||||
JSGC_MAX_NURSERY_BYTES = 2,
|
||||
|
||||
/** Amount of bytes allocated by the GC. */
|
||||
JSGC_BYTES = 3,
|
||||
|
||||
|
@ -2178,9 +2181,23 @@ JS_GetConstructor(JSContext* cx, JS::Handle<JSObject*> proto);
|
|||
|
||||
namespace JS {
|
||||
|
||||
// Specification for which zone a newly created compartment should use.
|
||||
enum ZoneSpecifier {
|
||||
FreshZone = 0,
|
||||
SystemZone = 1
|
||||
// Use the single runtime wide system zone. The meaning of this zone is
|
||||
// left to the embedder.
|
||||
SystemZone,
|
||||
|
||||
// Use a particular existing zone.
|
||||
ExistingZone,
|
||||
|
||||
// Create a new zone with its own new zone group.
|
||||
NewZoneInNewZoneGroup,
|
||||
|
||||
// Create a new zone in the same zone group as the system zone.
|
||||
NewZoneInSystemZoneGroup,
|
||||
|
||||
// Create a new zone in the same zone group as another existing zone.
|
||||
NewZoneInExistingZoneGroup
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2197,6 +2214,8 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
|
|||
CompartmentCreationOptions()
|
||||
: addonId_(nullptr),
|
||||
traceGlobal_(nullptr),
|
||||
zoneSpec_(NewZoneInSystemZoneGroup),
|
||||
zonePointer_(nullptr),
|
||||
invisibleToDebugger_(false),
|
||||
mergeable_(false),
|
||||
preserveJitCode_(false),
|
||||
|
@ -2204,9 +2223,7 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
|
|||
experimentalNumberFormatFormatToPartsEnabled_(false),
|
||||
sharedMemoryAndAtomics_(false),
|
||||
secureContext_(false)
|
||||
{
|
||||
zone_.spec = JS::FreshZone;
|
||||
}
|
||||
{}
|
||||
|
||||
// A null add-on ID means that the compartment is not associated with an
|
||||
// add-on.
|
||||
|
@ -2224,13 +2241,15 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void* zonePointer() const {
|
||||
MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
|
||||
return zone_.pointer;
|
||||
}
|
||||
ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
|
||||
CompartmentCreationOptions& setZone(ZoneSpecifier spec);
|
||||
CompartmentCreationOptions& setSameZoneAs(JSObject* obj);
|
||||
void* zonePointer() const { return zonePointer_; }
|
||||
ZoneSpecifier zoneSpecifier() const { return zoneSpec_; }
|
||||
|
||||
// Set the zone to use for the compartment. See ZoneSpecifier above.
|
||||
CompartmentCreationOptions& setSystemZone();
|
||||
CompartmentCreationOptions& setExistingZone(JSObject* obj);
|
||||
CompartmentCreationOptions& setNewZoneInNewZoneGroup();
|
||||
CompartmentCreationOptions& setNewZoneInSystemZoneGroup();
|
||||
CompartmentCreationOptions& setNewZoneInExistingZoneGroup(JSObject* obj);
|
||||
|
||||
// Certain scopes (i.e. XBL compilation scopes) are implementation details
|
||||
// of the embedding, and references to them should never leak out to script.
|
||||
|
@ -2299,10 +2318,8 @@ class JS_PUBLIC_API(CompartmentCreationOptions)
|
|||
private:
|
||||
JSAddonId* addonId_;
|
||||
JSTraceOp traceGlobal_;
|
||||
union {
|
||||
ZoneSpecifier spec;
|
||||
void* pointer; // js::Zone* is not exposed in the API.
|
||||
} zone_;
|
||||
ZoneSpecifier zoneSpec_;
|
||||
void* zonePointer_; // Per zoneSpec_, either a Zone, ZoneGroup, or null.
|
||||
bool invisibleToDebugger_;
|
||||
bool mergeable_;
|
||||
bool preserveJitCode_;
|
||||
|
|
|
@ -176,10 +176,28 @@ js::DestroyContext(JSContext* cx)
|
|||
|
||||
cx->checkNoGCRooters();
|
||||
|
||||
js_delete(cx->ionPcScriptCache.ref());
|
||||
// Cancel all off thread Ion compiles before destroying a cooperative
|
||||
// context. Completed Ion compiles may try to interrupt arbitrary
|
||||
// cooperative contexts which they have read off the owner context of a
|
||||
// zone group. See HelperThread::handleIonWorkload.
|
||||
CancelOffThreadIonCompile(cx->runtime());
|
||||
|
||||
cx->runtime()->destroyRuntime();
|
||||
js_delete(cx->runtime());
|
||||
if (cx->runtime()->cooperatingContexts().length() == 1) {
|
||||
// Destroy the runtime along with its last context.
|
||||
cx->runtime()->destroyRuntime();
|
||||
js_delete(cx->runtime());
|
||||
} else {
|
||||
DebugOnly<bool> found = false;
|
||||
for (size_t i = 0; i < cx->runtime()->cooperatingContexts().length(); i++) {
|
||||
CooperatingContext& target = cx->runtime()->cooperatingContexts()[i];
|
||||
if (cx == target.context()) {
|
||||
cx->runtime()->cooperatingContexts().erase(&target);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(found);
|
||||
}
|
||||
|
||||
js_delete_poison(cx);
|
||||
}
|
||||
|
@ -1034,6 +1052,8 @@ JSContext::~JSContext()
|
|||
/* Free the stuff hanging off of cx. */
|
||||
MOZ_ASSERT(!resolvingList);
|
||||
|
||||
js_delete(ionPcScriptCache.ref());
|
||||
|
||||
if (dtoaState)
|
||||
DestroyDtoaState(dtoaState);
|
||||
|
||||
|
|
|
@ -406,10 +406,6 @@ struct JSCompartment
|
|||
return runtime_;
|
||||
}
|
||||
|
||||
JSContext* contextFromMainThread() const {
|
||||
return runtime_->contextFromMainThread();
|
||||
}
|
||||
|
||||
/*
|
||||
* Nb: global_ might be nullptr, if (a) it's the atoms compartment, or
|
||||
* (b) the compartment's global has been collected. The latter can happen
|
||||
|
|
|
@ -810,6 +810,7 @@ GCRuntime::releaseArena(Arena* arena, const AutoLockGC& lock)
|
|||
GCRuntime::GCRuntime(JSRuntime* rt) :
|
||||
rt(rt),
|
||||
systemZone(nullptr),
|
||||
systemZoneGroup(nullptr),
|
||||
atomsZone(nullptr),
|
||||
stats_(rt),
|
||||
marker(rt),
|
||||
|
@ -1044,6 +1045,7 @@ GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
|||
* for default backward API compatibility.
|
||||
*/
|
||||
MOZ_ALWAYS_TRUE(tunables.setParameter(JSGC_MAX_BYTES, maxbytes, lock));
|
||||
MOZ_ALWAYS_TRUE(tunables.setParameter(JSGC_MAX_NURSERY_BYTES, maxNurseryBytes, lock));
|
||||
setMaxMallocBytes(maxbytes);
|
||||
|
||||
const char* size = getenv("JSGC_MARK_STACK_LIMIT");
|
||||
|
@ -1165,6 +1167,9 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
|
|||
case JSGC_MAX_BYTES:
|
||||
gcMaxBytes_ = value;
|
||||
break;
|
||||
case JSGC_MAX_NURSERY_BYTES:
|
||||
gcMaxNurseryBytes_ = value;
|
||||
break;
|
||||
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
|
||||
highFrequencyThresholdUsec_ = value * PRMJ_USEC_PER_MSEC;
|
||||
break;
|
||||
|
@ -3550,9 +3555,7 @@ GCRuntime::sweepZoneGroups(FreeOp* fop, bool destroyingRuntime)
|
|||
ZoneGroup* group = *read++;
|
||||
sweepZones(fop, group, destroyingRuntime);
|
||||
|
||||
// For now, the singleton zone group is not destroyed until the runtime
|
||||
// itself is, bug 1323066.
|
||||
if (group->zones().empty() && group != rt->zoneGroupFromMainThread()) {
|
||||
if (group->zones().empty()) {
|
||||
MOZ_ASSERT(numActiveZoneIters == 0);
|
||||
fop->delete_(group);
|
||||
} else {
|
||||
|
@ -6169,7 +6172,6 @@ namespace {
|
|||
class AutoScheduleZonesForGC
|
||||
{
|
||||
JSRuntime* rt_;
|
||||
AutoAccessZoneGroups aazg;
|
||||
|
||||
public:
|
||||
explicit AutoScheduleZonesForGC(JSRuntime* rt) : rt_(rt) {
|
||||
|
@ -6187,9 +6189,6 @@ class AutoScheduleZonesForGC
|
|||
{
|
||||
zone->scheduleGC();
|
||||
}
|
||||
|
||||
if (zone->isGCScheduled() && !zone->isAtomsZone())
|
||||
aazg.access(zone->group());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6753,15 +6752,61 @@ AutoPrepareForTracing::AutoPrepareForTracing(JSContext* cx, ZoneSelector selecto
|
|||
}
|
||||
|
||||
JSCompartment*
|
||||
js::NewCompartment(JSContext* cx, Zone* zone, JSPrincipals* principals,
|
||||
js::NewCompartment(JSContext* cx, JSPrincipals* principals,
|
||||
const JS::CompartmentOptions& options)
|
||||
{
|
||||
JSRuntime* rt = cx->runtime();
|
||||
JS_AbortIfWrongThread(cx);
|
||||
|
||||
ScopedJSDeletePtr<ZoneGroup> groupHolder;
|
||||
ScopedJSDeletePtr<Zone> zoneHolder;
|
||||
|
||||
Zone* zone = nullptr;
|
||||
ZoneGroup* group = nullptr;
|
||||
JS::ZoneSpecifier zoneSpec = options.creationOptions().zoneSpecifier();
|
||||
switch (zoneSpec) {
|
||||
case JS::SystemZone:
|
||||
// systemZone and possibly systemZoneGroup might be null here, in which
|
||||
// case we'll make a zone/group and set these fields below.
|
||||
zone = rt->gc.systemZone;
|
||||
group = rt->gc.systemZoneGroup;
|
||||
break;
|
||||
case JS::ExistingZone:
|
||||
zone = static_cast<Zone*>(options.creationOptions().zonePointer());
|
||||
MOZ_ASSERT(zone);
|
||||
group = zone->group();
|
||||
break;
|
||||
case JS::NewZoneInNewZoneGroup:
|
||||
break;
|
||||
case JS::NewZoneInSystemZoneGroup:
|
||||
// As above, systemZoneGroup might be null here.
|
||||
group = rt->gc.systemZoneGroup;
|
||||
break;
|
||||
case JS::NewZoneInExistingZoneGroup:
|
||||
group = static_cast<ZoneGroup*>(options.creationOptions().zonePointer());
|
||||
MOZ_ASSERT(group);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!group) {
|
||||
MOZ_ASSERT(!zone);
|
||||
group = cx->new_<ZoneGroup>(rt);
|
||||
if (!group)
|
||||
return nullptr;
|
||||
|
||||
groupHolder.reset(group);
|
||||
|
||||
if (!group->init(rt->gc.tunables.gcMaxNurseryBytes())) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cx->generationalDisabled)
|
||||
group->nursery().disable();
|
||||
}
|
||||
|
||||
if (!zone) {
|
||||
zone = cx->new_<Zone>(cx->runtime(), rt->zoneGroupFromMainThread());
|
||||
zone = cx->new_<Zone>(cx->runtime(), group);
|
||||
if (!zone)
|
||||
return nullptr;
|
||||
|
||||
|
@ -6789,12 +6834,35 @@ js::NewCompartment(JSContext* cx, Zone* zone, JSPrincipals* principals,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (zoneHolder && zoneHolder->group() && !zoneHolder->group()->zones().append(zone)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
if (zoneHolder) {
|
||||
if (!group->zones().append(zone)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Lazily set the runtime's sytem zone.
|
||||
if (zoneSpec == JS::SystemZone) {
|
||||
MOZ_RELEASE_ASSERT(!rt->gc.systemZone);
|
||||
rt->gc.systemZone = zone;
|
||||
zone->isSystem = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (groupHolder) {
|
||||
if (!rt->gc.groups.ref().append(group)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Lazily set the runtime's system zone group.
|
||||
if (zoneSpec == JS::SystemZone || zoneSpec == JS::NewZoneInSystemZoneGroup) {
|
||||
MOZ_RELEASE_ASSERT(!rt->gc.systemZoneGroup);
|
||||
rt->gc.systemZoneGroup = group;
|
||||
}
|
||||
}
|
||||
|
||||
zoneHolder.forget();
|
||||
groupHolder.forget();
|
||||
return compartment.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -1057,7 +1057,7 @@ extern void
|
|||
FinalizeStringRT(JSRuntime* rt, JSString* str);
|
||||
|
||||
JSCompartment*
|
||||
NewCompartment(JSContext* cx, JS::Zone* zone, JSPrincipals* principals,
|
||||
NewCompartment(JSContext* cx, JSPrincipals* principals,
|
||||
const JS::CompartmentOptions& options);
|
||||
|
||||
namespace gc {
|
||||
|
|
|
@ -3364,12 +3364,12 @@ EvalInContext(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
struct WorkerInput
|
||||
{
|
||||
JSContext* context;
|
||||
JSRuntime* parentRuntime;
|
||||
char16_t* chars;
|
||||
size_t length;
|
||||
|
||||
WorkerInput(JSContext* context, char16_t* chars, size_t length)
|
||||
: context(context), chars(chars), length(length)
|
||||
WorkerInput(JSRuntime* parentRuntime, char16_t* chars, size_t length)
|
||||
: parentRuntime(parentRuntime), chars(chars), length(length)
|
||||
{}
|
||||
|
||||
~WorkerInput() {
|
||||
|
@ -3384,7 +3384,7 @@ WorkerMain(void* arg)
|
|||
{
|
||||
WorkerInput* input = (WorkerInput*) arg;
|
||||
|
||||
JSContext* cx = JS_NewContext(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->context);
|
||||
JSContext* cx = JS_NewContext(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->parentRuntime);
|
||||
if (!cx) {
|
||||
js_delete(input);
|
||||
return;
|
||||
|
@ -3513,7 +3513,7 @@ EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
CopyChars(chars, *str);
|
||||
|
||||
WorkerInput* input = js_new<WorkerInput>(JS_GetParentContext(cx), chars, str->length());
|
||||
WorkerInput* input = js_new<WorkerInput>(JS_GetParentRuntime(cx), chars, str->length());
|
||||
if (!input) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -4846,7 +4846,7 @@ NewGlobal(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!JS_GetProperty(cx, opts, "sameZoneAs", &v))
|
||||
return false;
|
||||
if (v.isObject())
|
||||
creationOptions.setSameZoneAs(UncheckedUnwrap(&v.toObject()));
|
||||
creationOptions.setExistingZone(UncheckedUnwrap(&v.toObject()));
|
||||
|
||||
if (!JS_GetProperty(cx, opts, "disableLazyParsing", &v))
|
||||
return false;
|
||||
|
|
|
@ -346,27 +346,10 @@ GlobalObject::new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
|
|||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
|
||||
auto zoneSpecifier = options.creationOptions().zoneSpecifier();
|
||||
Zone* zone;
|
||||
if (zoneSpecifier == JS::SystemZone)
|
||||
zone = rt->gc.systemZone;
|
||||
else if (zoneSpecifier == JS::FreshZone)
|
||||
zone = nullptr;
|
||||
else
|
||||
zone = static_cast<Zone*>(options.creationOptions().zonePointer());
|
||||
|
||||
JSCompartment* compartment = NewCompartment(cx, zone, principals, options);
|
||||
JSCompartment* compartment = NewCompartment(cx, principals, options);
|
||||
if (!compartment)
|
||||
return nullptr;
|
||||
|
||||
// Lazily create the system zone.
|
||||
if (!rt->gc.systemZone && zoneSpecifier == JS::SystemZone) {
|
||||
rt->gc.systemZone = compartment->zone();
|
||||
rt->gc.systemZone->isSystem = true;
|
||||
}
|
||||
|
||||
Rooted<GlobalObject*> global(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, compartment);
|
||||
|
|
|
@ -541,7 +541,7 @@ CreateGlobalForOffThreadParse(JSContext* cx, ParseTaskKind kind, const gc::AutoS
|
|||
|
||||
creationOptions.setInvisibleToDebugger(true)
|
||||
.setMergeable(true)
|
||||
.setZone(JS::FreshZone);
|
||||
.setNewZoneInSystemZoneGroup();
|
||||
|
||||
// Don't falsely inherit the host's global trace hook.
|
||||
creationOptions.setTrace(nullptr);
|
||||
|
@ -1565,15 +1565,24 @@ HelperThread::handleIonWorkload(AutoLockHelperThreadState& locked)
|
|||
}
|
||||
|
||||
FinishOffThreadIonCompile(builder, locked);
|
||||
|
||||
// Ping any thread currently operating on the compiled script's zone group
|
||||
// so that the compiled code can be incorporated at the next interrupt
|
||||
// callback. Don't interrupt Ion code for this, as this incorporation can
|
||||
// be delayed indefinitely without affecting performance as long as the
|
||||
// main thread is actually executing Ion code.
|
||||
//
|
||||
// This must happen before the current task is reset. DestroyContext
|
||||
// cancels in progress Ion compilations before destroying its target
|
||||
// context, and after we reset the current task we are no longer considered
|
||||
// to be Ion compiling.
|
||||
JSContext* target = builder->script()->zoneFromAnyThread()->group()->ownerContext().context();
|
||||
if (target)
|
||||
target->requestInterrupt(JSContext::RequestInterruptCanWait);
|
||||
|
||||
currentTask.reset();
|
||||
pause = false;
|
||||
|
||||
// Ping the main thread so that the compiled code can be incorporated
|
||||
// at the next interrupt callback. Don't interrupt Ion code for this, as
|
||||
// this incorporation can be delayed indefinitely without affecting
|
||||
// performance as long as the main thread is actually executing Ion code.
|
||||
rt->unsafeContextFromAnyThread()->requestInterrupt(JSContext::RequestInterruptCanWait);
|
||||
|
||||
// Notify the main thread in case it is waiting for the compilation to finish.
|
||||
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
||||
|
||||
|
|
|
@ -143,8 +143,6 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
|||
lcovOutput_(),
|
||||
jitRuntime_(nullptr),
|
||||
selfHostingGlobal_(nullptr),
|
||||
singletonContext(nullptr),
|
||||
singletonZoneGroup(nullptr),
|
||||
gc(thisFromCtor()),
|
||||
gcInitialized(false),
|
||||
NaNValue(DoubleNaNValue()),
|
||||
|
@ -199,24 +197,13 @@ JSRuntime::init(JSContext* cx, uint32_t maxbytes, uint32_t maxNurseryBytes)
|
|||
if (!cooperatingContexts().append(cx))
|
||||
return false;
|
||||
|
||||
singletonContext = cx;
|
||||
|
||||
defaultFreeOp_ = js_new<js::FreeOp>(this);
|
||||
if (!defaultFreeOp_)
|
||||
return false;
|
||||
|
||||
ScopedJSDeletePtr<ZoneGroup> zoneGroup(js_new<ZoneGroup>(this));
|
||||
if (!zoneGroup)
|
||||
return false;
|
||||
singletonZoneGroup = zoneGroup;
|
||||
|
||||
if (!gc.init(maxbytes, maxNurseryBytes))
|
||||
return false;
|
||||
|
||||
if (!zoneGroup->init(maxNurseryBytes) || !gc.groups.ref().append(zoneGroup))
|
||||
return false;
|
||||
zoneGroup.forget();
|
||||
|
||||
ScopedJSDeletePtr<Zone> atomsZone(new_<Zone>(this, nullptr));
|
||||
if (!atomsZone || !atomsZone->init(true))
|
||||
return false;
|
||||
|
@ -342,8 +329,6 @@ JSRuntime::destroyRuntime()
|
|||
|
||||
DebugOnly<size_t> oldCount = liveRuntimesCount--;
|
||||
MOZ_ASSERT(oldCount > 0);
|
||||
|
||||
js_delete(zoneGroupFromMainThread());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -616,24 +616,6 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
|
|||
return !!jitRuntime_;
|
||||
}
|
||||
|
||||
// These will be removed soon.
|
||||
private:
|
||||
JSContext* singletonContext;
|
||||
js::ZoneGroup* singletonZoneGroup;
|
||||
public:
|
||||
|
||||
JSContext* unsafeContextFromAnyThread() const { return singletonContext; }
|
||||
JSContext* contextFromMainThread() const {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
|
||||
return singletonContext;
|
||||
}
|
||||
|
||||
js::ZoneGroup* zoneGroupFromAnyThread() const { return singletonZoneGroup; }
|
||||
js::ZoneGroup* zoneGroupFromMainThread() const {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
|
||||
return singletonZoneGroup;
|
||||
}
|
||||
|
||||
private:
|
||||
// Used to generate random keys for hash tables.
|
||||
mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
|
||||
|
|
|
@ -2745,10 +2745,10 @@ JSRuntime::createSelfHostingGlobal(JSContext* cx)
|
|||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::FreshZone);
|
||||
options.creationOptions().setNewZoneInSystemZoneGroup();
|
||||
options.behaviors().setDiscardSource(true);
|
||||
|
||||
JSCompartment* compartment = NewCompartment(cx, nullptr, nullptr, options);
|
||||
JSCompartment* compartment = NewCompartment(cx, nullptr, options);
|
||||
if (!compartment)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -562,7 +562,7 @@ mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx,
|
|||
CompartmentOptions options;
|
||||
|
||||
options.creationOptions()
|
||||
.setZone(SystemZone)
|
||||
.setSystemZone()
|
||||
.setAddonId(aReuseLoaderGlobal ? nullptr : MapURIToAddonID(aURI));
|
||||
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
|
|
|
@ -1067,11 +1067,11 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
|
|||
creationOptions.setSharedMemoryAndAtomicsEnabled(true);
|
||||
|
||||
if (options.sameZoneAs)
|
||||
creationOptions.setSameZoneAs(js::UncheckedUnwrap(options.sameZoneAs));
|
||||
creationOptions.setExistingZone(js::UncheckedUnwrap(options.sameZoneAs));
|
||||
else if (options.freshZone)
|
||||
creationOptions.setZone(JS::FreshZone);
|
||||
creationOptions.setNewZoneInSystemZoneGroup();
|
||||
else
|
||||
creationOptions.setZone(JS::SystemZone);
|
||||
creationOptions.setSystemZone();
|
||||
|
||||
creationOptions.setInvisibleToDebugger(options.invisibleToDebugger)
|
||||
.setTrace(TraceXPCGlobal);
|
||||
|
|
|
@ -1522,7 +1522,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp,
|
|||
// Make the default XPCShell global use a fresh zone (rather than the
|
||||
// System Zone) to improve cross-zone test coverage.
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::FreshZone);
|
||||
options.creationOptions().setNewZoneInSystemZoneGroup();
|
||||
if (xpc::SharedMemoryEnabled())
|
||||
options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
|
|
|
@ -628,7 +628,7 @@ private:
|
|||
JSAutoRequest ar(mContext);
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setZone(JS::SystemZone);
|
||||
options.creationOptions().setSystemZone();
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr,
|
||||
JS::DontFireOnNewGlobalHook, options);
|
||||
|
|
|
@ -493,7 +493,7 @@ MozCrashWarningReporter(JSContext*, JSErrorReport*)
|
|||
}
|
||||
|
||||
nsresult
|
||||
CycleCollectedJSContext::Initialize(JSContext* aParentContext,
|
||||
CycleCollectedJSContext::Initialize(JSRuntime* aParentRuntime,
|
||||
uint32_t aMaxBytes,
|
||||
uint32_t aMaxNurseryBytes)
|
||||
{
|
||||
|
@ -504,7 +504,7 @@ CycleCollectedJSContext::Initialize(JSContext* aParentContext,
|
|||
mBaseRecursionDepth = RecursionDepth();
|
||||
|
||||
mozilla::dom::InitScriptSettings();
|
||||
mJSContext = JS_NewContext(aMaxBytes, aMaxNurseryBytes, aParentContext);
|
||||
mJSContext = JS_NewContext(aMaxBytes, aMaxNurseryBytes, aParentRuntime);
|
||||
if (!mJSContext) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ protected:
|
|||
virtual ~CycleCollectedJSContext();
|
||||
|
||||
MOZ_IS_CLASS_INIT
|
||||
nsresult Initialize(JSContext* aParentContext,
|
||||
nsresult Initialize(JSRuntime* aParentRuntime,
|
||||
uint32_t aMaxBytes,
|
||||
uint32_t aMaxNurseryBytes);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче