Bug 1452982 part 4 - Move jit-related fields from ZoneGroup to JitRuntime. r=jonco

This commit is contained in:
Jan de Mooij 2018-04-12 16:35:27 +02:00
Родитель 84ec03bf15
Коммит 1b0f7474cb
9 изменённых файлов: 126 добавлений и 126 удалений

Просмотреть файл

@ -2539,7 +2539,8 @@ testingFunc_bailAfter(JSContext* cx, unsigned argc, Value* vp)
}
#ifdef DEBUG
cx->zone()->group()->setIonBailAfter(args[0].toInt32());
if (auto* jitRuntime = cx->runtime()->jitRuntime())
jitRuntime->setIonBailAfter(args[0].toInt32());
#endif
args.rval().setUndefined();

Просмотреть файл

@ -19,24 +19,12 @@ ZoneGroup::ZoneGroup(JSRuntime* runtime)
: runtime(runtime),
helperThreadOwnerContext_(nullptr),
zones_(this),
helperThreadUse(HelperThreadUse::None),
#ifdef DEBUG
ionBailAfter_(this, 0),
#endif
numFinishedBuilders(0),
ionLazyLinkListSize_(0)
helperThreadUse(HelperThreadUse::None)
{}
ZoneGroup::~ZoneGroup()
{
#ifdef DEBUG
MOZ_ASSERT(helperThreadUse == HelperThreadUse::None);
{
AutoLockHelperThreadState lock;
MOZ_ASSERT(ionLazyLinkListSize_ == 0);
MOZ_ASSERT(ionLazyLinkList().isEmpty());
}
#endif
if (this == runtime->gc.systemZoneGroup)
runtime->gc.systemZoneGroup = nullptr;
@ -57,38 +45,6 @@ ZoneGroup::ownedByCurrentHelperThread()
return helperThreadOwnerContext_ == TlsContext.get();
}
ZoneGroup::IonBuilderList&
ZoneGroup::ionLazyLinkList()
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime),
"Should only be mutated by the active thread.");
return ionLazyLinkList_.ref();
}
void
ZoneGroup::ionLazyLinkListRemove(jit::IonBuilder* builder)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime),
"Should only be mutated by the active thread.");
MOZ_ASSERT(this == builder->script()->zone()->group());
MOZ_ASSERT(ionLazyLinkListSize_ > 0);
builder->removeFrom(ionLazyLinkList());
ionLazyLinkListSize_--;
MOZ_ASSERT(ionLazyLinkList().isEmpty() == (ionLazyLinkListSize_ == 0));
}
void
ZoneGroup::ionLazyLinkListAdd(jit::IonBuilder* builder)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime),
"Should only be mutated by the active thread.");
MOZ_ASSERT(this == builder->script()->zone()->group());
ionLazyLinkList().insertFront(builder);
ionLazyLinkListSize_++;
}
void
ZoneGroup::deleteEmptyZone(Zone* zone)
{

Просмотреть файл

@ -84,44 +84,6 @@ class ZoneGroup
// Delete an empty zone after its contents have been merged.
void deleteEmptyZone(Zone* zone);
#ifdef DEBUG
private:
// The number of possible bailing places encounters before forcefully bailing
// in that place. Zero means inactive.
ZoneGroupData<uint32_t> ionBailAfter_;
public:
void* addressOfIonBailAfter() { return &ionBailAfter_; }
// Set after how many bailing places we should forcefully bail.
// Zero disables this feature.
void setIonBailAfter(uint32_t after) {
ionBailAfter_ = after;
}
#endif
// Number of Ion compilations which were finished off thread and are
// waiting to be lazily linked. This is only set while holding the helper
// thread state lock, but may be read from at other times.
mozilla::Atomic<size_t> numFinishedBuilders;
private:
/* List of Ion compilation waiting to get linked. */
typedef mozilla::LinkedList<js::jit::IonBuilder> IonBuilderList;
js::HelperThreadLockData<IonBuilderList> ionLazyLinkList_;
js::HelperThreadLockData<size_t> ionLazyLinkListSize_;
public:
IonBuilderList& ionLazyLinkList();
size_t ionLazyLinkListSize() {
return ionLazyLinkListSize_;
}
void ionLazyLinkListRemove(js::jit::IonBuilder* builder);
void ionLazyLinkListAdd(js::jit::IonBuilder* builder);
};
} // namespace js

Просмотреть файл

@ -167,7 +167,7 @@ CompileZone::isAtomsZone()
const void*
CompileZone::addressOfIonBailAfter()
{
return zone()->group()->addressOfIonBailAfter();
return zone()->runtimeFromAnyThread()->jitRuntime()->addressOfIonBailAfter();
}
#endif

Просмотреть файл

@ -213,12 +213,21 @@ JitRuntime::JitRuntime()
baselineDebugModeOSRHandler_(nullptr),
trampolineCode_(nullptr),
functionWrappers_(nullptr),
jitcodeGlobalTable_(nullptr)
jitcodeGlobalTable_(nullptr),
#ifdef DEBUG
ionBailAfter_(0),
#endif
numFinishedBuilders_(0),
ionLazyLinkListSize_(0)
{
}
JitRuntime::~JitRuntime()
{
MOZ_ASSERT(numFinishedBuilders_ == 0);
MOZ_ASSERT(ionLazyLinkListSize_ == 0);
MOZ_ASSERT(ionLazyLinkList_.ref().isEmpty());
js_delete(functionWrappers_.ref());
// By this point, the jitcode global table should be empty.
@ -373,6 +382,38 @@ JitRuntime::debugTrapHandler(JSContext* cx)
return debugTrapHandler_;
}
JitRuntime::IonBuilderList&
JitRuntime::ionLazyLinkList(JSRuntime* rt)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt),
"Should only be mutated by the active thread.");
return ionLazyLinkList_.ref();
}
void
JitRuntime::ionLazyLinkListRemove(JSRuntime* rt, jit::IonBuilder* builder)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt),
"Should only be mutated by the active thread.");
MOZ_ASSERT(rt == builder->script()->runtimeFromActiveCooperatingThread());
MOZ_ASSERT(ionLazyLinkListSize_ > 0);
builder->removeFrom(ionLazyLinkList(rt));
ionLazyLinkListSize_--;
MOZ_ASSERT(ionLazyLinkList(rt).isEmpty() == (ionLazyLinkListSize_ == 0));
}
void
JitRuntime::ionLazyLinkListAdd(JSRuntime* rt, jit::IonBuilder* builder)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt),
"Should only be mutated by the active thread.");
MOZ_ASSERT(rt == builder->script()->runtimeFromActiveCooperatingThread());
ionLazyLinkList(rt).insertFront(builder);
ionLazyLinkListSize_++;
}
uint8_t*
JSContext::allocateOsrTempData(size_t size)
{
@ -485,7 +526,7 @@ jit::FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
// If the builder is still in one of the helper thread list, then remove it.
if (builder->isInList())
builder->script()->zone()->group()->ionLazyLinkListRemove(builder);
runtime->jitRuntime()->ionLazyLinkListRemove(runtime, builder);
// Clear the recompiling flag of the old ionScript, since we continue to
// use the old ionScript if recompiling fails.
@ -546,7 +587,7 @@ jit::LinkIonScript(JSContext* cx, HandleScript calleeScript)
calleeScript->baselineScript()->removePendingIonBuilder(cx->runtime(), calleeScript);
// Remove from pending.
cx->zone()->group()->ionLazyLinkListRemove(builder);
cx->runtime()->jitRuntime()->ionLazyLinkListRemove(cx->runtime(), builder);
}
{
@ -1896,14 +1937,14 @@ CompileBackEnd(MIRGenerator* mir)
// Find a builder which the current thread can finish.
static IonBuilder*
GetFinishedBuilder(ZoneGroup* group, GlobalHelperThreadState::IonBuilderVector& finished)
GetFinishedBuilder(JSRuntime* rt, GlobalHelperThreadState::IonBuilderVector& finished,
const AutoLockHelperThreadState& locked)
{
for (size_t i = 0; i < finished.length(); i++) {
IonBuilder* testBuilder = finished[i];
if (testBuilder->script()->runtimeFromAnyThread() == group->runtime &&
testBuilder->script()->zone()->group() == group) {
if (testBuilder->script()->runtimeFromAnyThread() == rt) {
HelperThreadState().remove(finished, &i);
group->numFinishedBuilders--;
rt->jitRuntime()->numFinishedBuildersRef(locked)--;
return testBuilder;
}
}
@ -1912,11 +1953,12 @@ GetFinishedBuilder(ZoneGroup* group, GlobalHelperThreadState::IonBuilderVector&
}
void
AttachFinishedCompilations(ZoneGroup* group, JSContext* maybecx)
AttachFinishedCompilations(JSContext* cx)
{
MOZ_ASSERT_IF(maybecx, maybecx->zone()->group() == group);
JSRuntime* rt = cx->runtime();
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
if (!group->numFinishedBuilders)
if (!rt->jitRuntime() || !rt->jitRuntime()->numFinishedBuilders())
return;
AutoLockHelperThreadState lock;
@ -1926,32 +1968,28 @@ AttachFinishedCompilations(ZoneGroup* group, JSContext* maybecx)
// finished, failed or have been cancelled.
while (true) {
// Find a finished builder for the zone group.
IonBuilder* builder = GetFinishedBuilder(group, finished);
IonBuilder* builder = GetFinishedBuilder(rt, finished, lock);
if (!builder)
break;
JSScript* script = builder->script();
MOZ_ASSERT(script->hasBaselineScript());
script->baselineScript()->setPendingIonBuilder(group->runtime, script, builder);
group->ionLazyLinkListAdd(builder);
script->baselineScript()->setPendingIonBuilder(rt, script, builder);
rt->jitRuntime()->ionLazyLinkListAdd(rt, builder);
// Don't keep more than 100 lazy link builders in a zone group.
// Link the oldest ones immediately. Only do this if we have a valid
// context to use (otherwise this method might have been called in the
// middle of a compartment change on the current thread's context).
if (maybecx) {
while (group->ionLazyLinkListSize() > 100) {
jit::IonBuilder* builder = group->ionLazyLinkList().getLast();
RootedScript script(maybecx, builder->script());
// Link the oldest ones immediately.
while (rt->jitRuntime()->ionLazyLinkListSize() > 100) {
jit::IonBuilder* builder = rt->jitRuntime()->ionLazyLinkList(rt).getLast();
RootedScript script(cx, builder->script());
AutoUnlockHelperThreadState unlock(lock);
AutoCompartment ac(maybecx, script);
jit::LinkIonScript(maybecx, script);
}
AutoUnlockHelperThreadState unlock(lock);
AutoCompartment ac(cx, script);
jit::LinkIonScript(cx, script);
}
}
MOZ_ASSERT(!group->numFinishedBuilders);
MOZ_ASSERT(!rt->jitRuntime()->numFinishedBuilders());
}
static void

Просмотреть файл

@ -145,7 +145,7 @@ LIRGraph* GenerateLIR(MIRGenerator* mir);
CodeGenerator* GenerateCode(MIRGenerator* mir, LIRGraph* lir);
CodeGenerator* CompileBackEnd(MIRGenerator* mir);
void AttachFinishedCompilations(ZoneGroup* group, JSContext* maybecx);
void AttachFinishedCompilations(JSContext* cx);
void FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
const AutoLockHelperThreadState& lock);
void FreeIonBuilder(IonBuilder* builder);

Просмотреть файл

@ -135,6 +135,22 @@ class JitRuntime
// Global table of jitcode native address => bytecode address mappings.
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_;
#ifdef DEBUG
// The number of possible bailing places encounters before forcefully bailing
// in that place. Zero means inactive.
ActiveThreadData<uint32_t> ionBailAfter_;
#endif
// Number of Ion compilations which were finished off thread and are
// waiting to be lazily linked. This is only set while holding the helper
// thread state lock, but may be read from at other times.
mozilla::Atomic<size_t> numFinishedBuilders_;
// List of Ion compilation waiting to get linked.
using IonBuilderList = mozilla::LinkedList<js::jit::IonBuilder>;
ActiveThreadData<IonBuilderList> ionLazyLinkList_;
ActiveThreadData<size_t> ionLazyLinkListSize_;
private:
void generateLazyLinkStub(MacroAssembler& masm);
void generateInterpreterStub(MacroAssembler& masm);
@ -275,6 +291,32 @@ class JitRuntime
bool isOptimizationTrackingEnabled(ZoneGroup* group) {
return isProfilerInstrumentationEnabled(group->runtime);
}
#ifdef DEBUG
void* addressOfIonBailAfter() { return &ionBailAfter_; }
// Set after how many bailing places we should forcefully bail.
// Zero disables this feature.
void setIonBailAfter(uint32_t after) {
ionBailAfter_ = after;
}
#endif
size_t numFinishedBuilders() const {
return numFinishedBuilders_;
}
mozilla::Atomic<size_t>& numFinishedBuildersRef(const AutoLockHelperThreadState& locked) {
return numFinishedBuilders_;
}
IonBuilderList& ionLazyLinkList(JSRuntime* rt);
size_t ionLazyLinkListSize() const {
return ionLazyLinkListSize_;
}
void ionLazyLinkListRemove(JSRuntime* rt, js::jit::IonBuilder* builder);
void ionLazyLinkListAdd(JSRuntime* rt, js::jit::IonBuilder* builder);
};
enum class CacheKind : uint8_t;

Просмотреть файл

@ -209,7 +209,7 @@ FinishOffThreadIonCompile(jit::IonBuilder* builder, const AutoLockHelperThreadSt
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!HelperThreadState().ionFinishedList(lock).append(builder))
oomUnsafe.crash("FinishOffThreadIonCompile");
builder->script()->zoneFromAnyThread()->group()->numFinishedBuilders++;
builder->script()->runtimeFromAnyThread()->jitRuntime()->numFinishedBuildersRef(lock)++;
}
static JSRuntime*
@ -309,8 +309,9 @@ CancelOffThreadIonCompileLocked(const CompilationSelector& selector, bool discar
for (size_t i = 0; i < finished.length(); i++) {
jit::IonBuilder* builder = finished[i];
if (IonBuilderMatches(selector, builder)) {
builder->script()->zoneFromAnyThread()->group()->numFinishedBuilders--;
jit::FinishOffThreadBuilder(builder->script()->runtimeFromAnyThread(), builder, lock);
JSRuntime* rt = builder->script()->runtimeFromAnyThread();
rt->jitRuntime()->numFinishedBuildersRef(lock)--;
jit::FinishOffThreadBuilder(rt, builder, lock);
HelperThreadState().remove(finished, &i);
}
}
@ -319,14 +320,12 @@ CancelOffThreadIonCompileLocked(const CompilationSelector& selector, bool discar
if (discardLazyLinkList) {
MOZ_ASSERT(!selector.is<AllCompilations>());
JSRuntime* runtime = GetSelectorRuntime(selector);
for (ZoneGroupsIter group(runtime); !group.done(); group.next()) {
jit::IonBuilder* builder = group->ionLazyLinkList().getFirst();
while (builder) {
jit::IonBuilder* next = builder->getNext();
if (IonBuilderMatches(selector, builder))
jit::FinishOffThreadBuilder(runtime, builder, lock);
builder = next;
}
jit::IonBuilder* builder = runtime->jitRuntime()->ionLazyLinkList(runtime).getFirst();
while (builder) {
jit::IonBuilder* next = builder->getNext();
if (IonBuilderMatches(selector, builder))
jit::FinishOffThreadBuilder(runtime, builder, lock);
builder = next;
}
}
}
@ -369,7 +368,8 @@ js::HasOffThreadIonCompile(JSCompartment* comp)
return true;
}
jit::IonBuilder* builder = comp->zone()->group()->ionLazyLinkList().getFirst();
JSRuntime* rt = comp->runtimeFromActiveCooperatingThread();
jit::IonBuilder* builder = rt->jitRuntime()->ionLazyLinkList(rt).getFirst();
while (builder) {
if (builder->script()->compartment() == comp)
return true;
@ -2108,8 +2108,9 @@ GlobalHelperThreadState::trace(JSTracer* trc, gc::AutoTraceSession& session)
}
}
for (ZoneGroupsIter group(trc->runtime()); !group.done(); group.next()) {
jit::IonBuilder* builder = group->ionLazyLinkList().getFirst();
JSRuntime* rt = trc->runtime();
if (auto* jitRuntime = rt->jitRuntime()) {
jit::IonBuilder* builder = jitRuntime->ionLazyLinkList(rt).getFirst();
while (builder) {
builder->trace(trc);
builder = builder->getNext();

Просмотреть файл

@ -434,7 +434,7 @@ InvokeInterruptCallback(JSContext* cx)
// A worker thread may have requested an interrupt after finishing an Ion
// compilation.
jit::AttachFinishedCompilations(cx->zone()->group(), cx);
jit::AttachFinishedCompilations(cx);
// Important: Additional callbacks can occur inside the callback handler
// if it re-enters the JS engine. The embedding must ensure that the