Commit bc64716d authored by Jan de Mooij's avatar Jan de Mooij
Browse files

Bug 1598548 part 8 - Fold JSOP_LOOPENTRY into JSOP_LOOPHEAD. r=tcampbell

Mechanical rename/merge for the most part.

When restarting a loop in IonBuilder, we skip the JSOP_LOOPHEAD so we
now re-add the interrupt check (this used to be done by JSOP_LOOPENTRY)
explicitly by calling emitLoopHeadInstructions.

Differential Revision: https://phabricator.services.mozilla.com/D55632

--HG--
extra : moz-landing-system : lando
parent 2d2df976
......@@ -1672,7 +1672,6 @@ static bool BytecodeIsEffectful(JSOp op) {
case JSOP_IS_CONSTRUCTING:
case JSOP_OPTIMIZE_SPREADCALL:
case JSOP_IMPORTMETA:
case JSOP_LOOPENTRY:
case JSOP_INSTRUMENTATION_ACTIVE:
case JSOP_INSTRUMENTATION_CALLBACK:
case JSOP_INSTRUMENTATION_SCRIPT_ID:
......@@ -1715,6 +1714,7 @@ static bool BytecodeIsEffectful(JSOp op) {
case JSOP_UNUSED106:
case JSOP_UNUSED120:
case JSOP_UNUSED149:
case JSOP_UNUSED227:
case JSOP_LIMIT:
return false;
}
......
......@@ -103,17 +103,12 @@ bool LoopControl::emitLoopHead(BytecodeEmitter* bce,
MOZ_ASSERT(loopDepth_ > 0);
head_ = {bce->bytecodeSection().offset()};
BytecodeOffset headOff;
if (!bce->emitJumpTargetOp(JSOP_LOOPHEAD, &headOff)) {
BytecodeOffset off;
if (!bce->emitJumpTargetOp(JSOP_LOOPHEAD, &off)) {
return false;
}
BytecodeOffset entryOff;
if (!bce->emitJumpTargetOp(JSOP_LOOPENTRY, &entryOff)) {
return false;
}
SetLoopEntryDepthHintAndFlags(bce->bytecodeSection().code(entryOff),
loopDepth_, canIonOsr_);
SetLoopHeadDepthHintAndFlags(bce->bytecodeSection().code(off), loopDepth_,
canIonOsr_);
return true;
}
......
......@@ -440,19 +440,18 @@ static inline void* GetStubReturnAddress(JSContext* cx, JSOp op) {
return code.bailoutReturnAddr(BailoutReturnKind::Call);
}
static inline jsbytecode* GetNextNonLoopEntryPc(jsbytecode* pc,
jsbytecode** skippedLoopEntry) {
static inline jsbytecode* GetNextNonLoopHeadPc(jsbytecode* pc,
jsbytecode** skippedLoopHead) {
JSOp op = JSOp(*pc);
switch (op) {
case JSOP_GOTO:
return pc + GET_JUMP_OFFSET(pc);
case JSOP_LOOPENTRY:
*skippedLoopEntry = pc;
case JSOP_LOOPHEAD:
*skippedLoopHead = pc;
return GetNextPc(pc);
case JSOP_NOP:
case JSOP_LOOPHEAD:
return GetNextPc(pc);
default:
......@@ -467,22 +466,22 @@ static jsbytecode* GetResumePC(JSScript* script, jsbytecode* pc,
return GetNextPc(pc);
}
// If we are resuming at a LOOPENTRY op, resume at the next op to avoid
// If we are resuming at a LOOPHEAD op, resume at the next op to avoid
// a bailout -> enter Ion -> bailout loop with --ion-eager.
//
// The algorithm below is the "tortoise and the hare" algorithm. See bug
// 994444 for more explanation.
jsbytecode* skippedLoopEntry = nullptr;
jsbytecode* skippedLoopHead = nullptr;
jsbytecode* fasterPc = pc;
while (true) {
pc = GetNextNonLoopEntryPc(pc, &skippedLoopEntry);
fasterPc = GetNextNonLoopEntryPc(fasterPc, &skippedLoopEntry);
fasterPc = GetNextNonLoopEntryPc(fasterPc, &skippedLoopEntry);
pc = GetNextNonLoopHeadPc(pc, &skippedLoopHead);
fasterPc = GetNextNonLoopHeadPc(fasterPc, &skippedLoopHead);
fasterPc = GetNextNonLoopHeadPc(fasterPc, &skippedLoopHead);
if (fasterPc == pc) {
break;
}
}
if (skippedLoopEntry && script->trackRecordReplayProgress()) {
if (skippedLoopHead && script->trackRecordReplayProgress()) {
mozilla::recordreplay::AdvanceExecutionProgressCounter();
}
......
......@@ -1282,7 +1282,7 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
// if --ion-eager is used.
JSScript* script = handler.script();
jsbytecode* pc = handler.pc();
if (JSOp(*pc) == JSOP_LOOPENTRY) {
if (JSOp(*pc) == JSOP_LOOPHEAD) {
uint32_t pcOffset = script->pcToOffset(pc);
uint32_t nativeOffset = masm.currentOffset();
if (!handler.osrEntries().emplaceBack(pcOffset, nativeOffset)) {
......@@ -1309,15 +1309,15 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
masm.add32(Imm32(1), countReg);
masm.store32(countReg, warmUpCounterAddr);
if (JSOp(*pc) == JSOP_LOOPENTRY) {
if (JSOp(*pc) == JSOP_LOOPHEAD) {
// If this is a loop inside a catch or finally block, increment the warmup
// counter but don't attempt OSR (Ion only compiles the try block).
if (handler.analysis().info(pc).loopEntryInCatchOrFinally) {
if (handler.analysis().info(pc).loopHeadInCatchOrFinally) {
return true;
}
if (!LoopEntryCanIonOsr(pc)) {
// OSR into Ion not possible at this loop entry.
if (!LoopHeadCanIonOsr(pc)) {
// OSR into Ion not possible at this loop.
return true;
}
}
......@@ -1338,7 +1338,7 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
&done);
// Try to compile and/or finish a compilation.
if (JSOp(*pc) == JSOP_LOOPENTRY) {
if (JSOp(*pc) == JSOP_LOOPHEAD) {
// Try to OSR into Ion.
computeFrameSize(R0.scratchReg());
......@@ -2245,7 +2245,13 @@ bool BaselineCodeGen<Handler>::emit_JSOP_LOOPHEAD() {
if (!emit_JSOP_JUMPTARGET()) {
return false;
}
return emitInterruptCheck();
if (!emitInterruptCheck()) {
return false;
}
if (!emitWarmUpCounterIncrement()) {
return false;
}
return emitIncExecutionProgressCounter(R0.scratchReg());
}
template <typename Handler>
......@@ -2264,19 +2270,6 @@ bool BaselineCodeGen<Handler>::emitIncExecutionProgressCounter(
true, incCounter, scratch);
}
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_LOOPENTRY() {
if (!emit_JSOP_JUMPTARGET()) {
return false;
}
frame.syncStack(0);
if (!emitWarmUpCounterIncrement()) {
return false;
}
return emitIncExecutionProgressCounter(R0.scratchReg());
}
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_VOID() {
frame.pop();
......@@ -6941,6 +6934,7 @@ MethodStatus BaselineCompiler::emitBody() {
case JSOP_UNUSED106:
case JSOP_UNUSED120:
case JSOP_UNUSED149:
case JSOP_UNUSED227:
case JSOP_LIMIT:
MOZ_CRASH("Unexpected op");
......
......@@ -42,7 +42,6 @@ namespace jit {
_(JSOP_POS) \
_(JSOP_TONUMERIC) \
_(JSOP_LOOPHEAD) \
_(JSOP_LOOPENTRY) \
_(JSOP_VOID) \
_(JSOP_UNDEFINED) \
_(JSOP_HOLE) \
......
......@@ -138,7 +138,7 @@ static JitExecStatus EnterBaseline(JSContext* cx, EnterJitData& data) {
JitExecStatus jit::EnterBaselineInterpreterAtBranch(JSContext* cx,
InterpreterFrame* fp,
jsbytecode* pc) {
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPHEAD);
EnterJitData data(cx);
......@@ -410,7 +410,7 @@ bool jit::BaselineCompileFromBaselineInterpreter(JSContext* cx,
RootedScript script(cx, frame->script());
jsbytecode* pc = frame->interpreterPC();
MOZ_ASSERT(pc == script->code() || *pc == JSOP_LOOPENTRY);
MOZ_ASSERT(pc == script->code() || *pc == JSOP_LOOPHEAD);
MethodStatus status = CanEnterBaselineJIT(cx, script,
/* osrSourceFrame = */ frame);
......@@ -424,7 +424,7 @@ bool jit::BaselineCompileFromBaselineInterpreter(JSContext* cx,
return true;
case Method_Compiled: {
if (*pc == JSOP_LOOPENTRY) {
if (*pc == JSOP_LOOPHEAD) {
BaselineScript* baselineScript = script->baselineScript();
uint32_t pcOffset = script->pcToOffset(pc);
*res = baselineScript->nativeCodeForOSREntry(pcOffset);
......
......@@ -155,10 +155,10 @@ bool BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn) {
break;
}
case JSOP_LOOPENTRY:
case JSOP_LOOPHEAD:
for (size_t i = 0; i < catchFinallyRanges.length(); i++) {
if (catchFinallyRanges[i].contains(offset)) {
infos_[offset].loopEntryInCatchOrFinally = true;
infos_[offset].loopHeadInCatchOrFinally = true;
}
}
break;
......
......@@ -22,8 +22,8 @@ struct BytecodeInfo {
bool initialized : 1;
bool jumpTarget : 1;
// If true, this is a JSOP_LOOPENTRY op inside a catch or finally block.
bool loopEntryInCatchOrFinally : 1;
// If true, this is a JSOP_LOOPHEAD op inside a catch or finally block.
bool loopHeadInCatchOrFinally : 1;
// True if the script has a resume offset for this bytecode op.
bool hasResumeOffset : 1;
......
......@@ -187,7 +187,7 @@ class CompileInfo {
mayReadFrameArgsDirectly_(script->mayReadFrameArgsDirectly()),
trackRecordReplayProgress_(script->trackRecordReplayProgress()),
inlineScriptTree_(inlineScriptTree) {
MOZ_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
MOZ_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPHEAD);
// The function here can flow in from anywhere so look up the canonical
// function to ensure that we do not try to embed a nursery pointer in
......@@ -265,7 +265,7 @@ class CompileInfo {
InlineScriptTree* inlineScriptTree() const { return inlineScriptTree_; }
bool hasOsrAt(jsbytecode* pc) const {
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPHEAD);
return pc == osrPc();
}
......
......@@ -2072,7 +2072,7 @@ static MethodStatus Compile(JSContext* cx, HandleScript script,
jsbytecode* osrPc, bool forceRecompile = false) {
MOZ_ASSERT(jit::IsIonEnabled());
MOZ_ASSERT(jit::IsBaselineJitEnabled());
MOZ_ASSERT_IF(osrPc != nullptr, LoopEntryCanIonOsr(osrPc));
MOZ_ASSERT_IF(osrPc != nullptr, LoopHeadCanIonOsr(osrPc));
AutoGeckoProfilerEntry pseudoFrame(
cx, "Ion script compilation",
JS::ProfilingCategoryPair::JS_IonCompilation);
......@@ -2277,8 +2277,8 @@ static MethodStatus BaselineCanEnterAtBranch(JSContext* cx, HandleScript script,
uint32_t osrFrameSize,
jsbytecode* pc) {
MOZ_ASSERT(jit::IsIonEnabled());
MOZ_ASSERT((JSOp)*pc == JSOP_LOOPENTRY);
MOZ_ASSERT(LoopEntryCanIonOsr(pc));
MOZ_ASSERT((JSOp)*pc == JSOP_LOOPHEAD);
MOZ_ASSERT(LoopHeadCanIonOsr(pc));
// Skip if the script has been disabled.
if (!script->canIonCompile()) {
......@@ -2354,9 +2354,9 @@ static bool IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame,
MOZ_ASSERT(frame->debugFrameSize() == frameSize);
RootedScript script(cx, frame->script());
bool isLoopEntry = JSOp(*pc) == JSOP_LOOPENTRY;
bool isLoopHead = JSOp(*pc) == JSOP_LOOPHEAD;
MOZ_ASSERT(!isLoopEntry || LoopEntryCanIonOsr(pc));
MOZ_ASSERT(!isLoopHead || LoopHeadCanIonOsr(pc));
// The Baseline JIT code checks for Ion disabled or compiling off-thread.
MOZ_ASSERT(script->canIonCompile());
......@@ -2365,7 +2365,7 @@ static bool IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame,
// If Ion script exists, but PC is not at a loop entry, then Ion will be
// entered for this script at an appropriate LOOPENTRY or the next time this
// function is called.
if (script->hasIonScript() && !isLoopEntry) {
if (script->hasIonScript() && !isLoopHead) {
JitSpew(JitSpew_BaselineOSR, "IonScript exists, but not at loop entry!");
// TODO: ASSERT that a ion-script-already-exists checker stub doesn't exist.
// TODO: Clear all optimized stubs.
......@@ -2381,9 +2381,9 @@ static bool IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame,
(int)script->getWarmUpCount(), (void*)pc);
MethodStatus stat;
if (isLoopEntry) {
MOZ_ASSERT(LoopEntryCanIonOsr(pc));
JitSpew(JitSpew_BaselineOSR, " Compile at loop entry!");
if (isLoopHead) {
MOZ_ASSERT(LoopHeadCanIonOsr(pc));
JitSpew(JitSpew_BaselineOSR, " Compile at loop head!");
stat = BaselineCanEnterAtBranch(cx, script, frame, frameSize, pc);
} else if (frame->isFunctionFrame()) {
JitSpew(JitSpew_BaselineOSR,
......@@ -2511,7 +2511,7 @@ bool jit::IonCompileScriptForBaselineOSR(JSContext* cx, BaselineFrame* frame,
*infoPtr = nullptr;
MOZ_ASSERT(frame->debugFrameSize() == frameSize);
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPHEAD);
if (!IonCompileScriptForBaseline(cx, frame, frameSize, pc)) {
return false;
......
......@@ -963,7 +963,7 @@ AbortReasonOr<Ok> IonBuilder::build() {
}
#endif
insertRecompileCheck();
insertRecompileCheck(pc);
auto clearLastPriorResumePoint = mozilla::MakeScopeExit([&] {
// Discard unreferenced & pre-allocated resume points.
......@@ -1141,7 +1141,7 @@ AbortReasonOr<Ok> IonBuilder::buildInline(IonBuilder* callerBuilder,
}
#endif
insertRecompileCheck();
insertRecompileCheck(pc);
// Insert an interrupt check when recording or replaying, which will bump
// the record/replay system's progress counter.
......@@ -1656,11 +1656,9 @@ AbortReasonOr<Ok> IonBuilder::traverseBytecode() {
}
// Skip unreachable ops (for example code after a 'return' or 'throw') until
// we get to the next jump target. Note that JSOP_LOOPENTRY is a jump target
// op, but we always skip it here because it means the whole loop is
// unreachable.
// we get to the next jump target.
if (hasTerminatedBlock()) {
while (!BytecodeIsJumpTarget(JSOp(*pc)) || *pc == JSOP_LOOPENTRY) {
while (!BytecodeIsJumpTarget(JSOp(*pc))) {
pc = GetNextPc(pc);
if (pc == codeEnd) {
return Ok();
......@@ -1788,7 +1786,6 @@ AbortReasonOr<Ok> IonBuilder::jsop_loophead() {
// All loops have the following bytecode structure:
//
// LOOPHEAD ; source note (with offset to backedge)
// LOOPENTRY
// ...
// IFNE/IFEQ/GOTO to LOOPHEAD
......@@ -1806,9 +1803,6 @@ AbortReasonOr<Ok> IonBuilder::jsop_loophead() {
MOZ_ASSERT(JSOp(*backjump) == JSOP_IFNE || JSOp(*backjump) == JSOP_IFEQ ||
JSOp(*backjump) == JSOP_GOTO);
jsbytecode* loopEntry = GetNextPc(pc);
MOZ_ASSERT(JSOp(*loopEntry) == JSOP_LOOPENTRY);
if (hasTerminatedBlock()) {
// The whole loop is unreachable, just skip it.
nextpc = GetNextPc(backjump);
......@@ -1830,21 +1824,21 @@ AbortReasonOr<Ok> IonBuilder::jsop_loophead() {
MOZ_CRASH("Unexpected source note");
}
bool canOsr = LoopEntryCanIonOsr(loopEntry);
bool osr = loopEntry == info().osrPc();
bool canOsr = LoopHeadCanIonOsr(pc);
bool osr = pc == info().osrPc();
if (osr) {
MOZ_ASSERT(canOsr);
MBasicBlock* preheader;
MOZ_TRY_VAR(preheader, newOsrPreheader(current, loopEntry));
MOZ_TRY_VAR(preheader, newOsrPreheader(current, pc));
current->end(MGoto::New(alloc(), preheader));
MOZ_TRY(setCurrentAndSpecializePhis(preheader));
}
loopDepth_++;
MBasicBlock* header;
MOZ_TRY_VAR(header, newPendingLoopHeader(current, loopEntry, osr, canOsr,
stackPhiCount));
MOZ_TRY_VAR(header,
newPendingLoopHeader(current, pc, osr, canOsr, stackPhiCount));
current->end(MGoto::New(alloc(), header));
if (!loopStack_.emplaceBack(header, GetNextPc(backjump))) {
......@@ -1853,7 +1847,8 @@ AbortReasonOr<Ok> IonBuilder::jsop_loophead() {
MOZ_TRY(analyzeNewLoopTypes(header, pc, pc, backjump));
return startTraversingBlock(header);
MOZ_TRY(startTraversingBlock(header));
return emitLoopHeadInstructions(pc);
}
AbortReasonOr<Ok> IonBuilder::visitBackEdge(bool* restarted) {
......@@ -1887,10 +1882,12 @@ AbortReasonOr<Ok> IonBuilder::visitBackEdge(bool* restarted) {
}
}
AbortReasonOr<Ok> IonBuilder::jsop_loopentry(bool* restarted) {
AbortReasonOr<Ok> IonBuilder::emitLoopHeadInstructions(jsbytecode* pc) {
MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPHEAD);
MInterruptCheck* check = MInterruptCheck::New(alloc());
current->add(check);
insertRecompileCheck();
insertRecompileCheck(pc);
if (script()->trackRecordReplayProgress()) {
check->setTrackRecordReplayProgress();
......@@ -2509,9 +2506,6 @@ AbortReasonOr<Ok> IonBuilder::inspectOpcode(JSOp op, bool* restarted) {
case JSOP_DYNAMIC_IMPORT:
return jsop_dynamic_import();
case JSOP_LOOPENTRY:
return jsop_loopentry(restarted);
case JSOP_INSTRUMENTATION_ACTIVE:
return jsop_instrumentation_active();
......@@ -2600,6 +2594,7 @@ AbortReasonOr<Ok> IonBuilder::inspectOpcode(JSOp op, bool* restarted) {
case JSOP_UNUSED106:
case JSOP_UNUSED120:
case JSOP_UNUSED149:
case JSOP_UNUSED227:
case JSOP_LIMIT:
break;
}
......@@ -2662,9 +2657,16 @@ AbortReasonOr<Ok> IonBuilder::restartLoop(MBasicBlock* header) {
// Don't specializePhis(), as the header has been visited before and the
// phis have already had their type set.
setCurrent(header);
nextpc = header->pc();
graph().addBlock(current);
jsbytecode* loopHead = header->pc();
MOZ_ASSERT(JSOp(*loopHead) == JSOP_LOOPHEAD);
// Since we discarded the header's instructions above, emit them again. This
// includes the interrupt check.
MOZ_TRY(emitLoopHeadInstructions(loopHead));
nextpc = GetNextPc(loopHead);
// Remove loop header and dead blocks from pendingBlocks.
for (PendingEdgesMap::Range r = pendingEdges_->all(); !r.empty();
r.popFront()) {
......@@ -7597,18 +7599,18 @@ AbortReasonOr<MBasicBlock*> IonBuilder::newBlockAfter(
}
AbortReasonOr<MBasicBlock*> IonBuilder::newOsrPreheader(
MBasicBlock* predecessor, jsbytecode* loopEntry) {
MOZ_ASSERT(JSOp(*loopEntry) == JSOP_LOOPENTRY);
MOZ_ASSERT(loopEntry == info().osrPc());
MBasicBlock* predecessor, jsbytecode* loopHead) {
MOZ_ASSERT(JSOp(*loopHead) == JSOP_LOOPHEAD);
MOZ_ASSERT(loopHead == info().osrPc());
// Create two blocks: one for the OSR entry with no predecessors, one for
// the preheader, which has the OSR entry block as a predecessor. The
// OSR block is always the second block (with id 1).
MBasicBlock* osrBlock;
MOZ_TRY_VAR(osrBlock, newBlockAfter(*graph().begin(),
predecessor->stackDepth(), loopEntry));
predecessor->stackDepth(), loopHead));
MBasicBlock* preheader;
MOZ_TRY_VAR(preheader, newBlock(predecessor, loopEntry));
MOZ_TRY_VAR(preheader, newBlock(predecessor, loopHead));
graph().addBlock(preheader);
......@@ -7737,7 +7739,7 @@ AbortReasonOr<MBasicBlock*> IonBuilder::newOsrPreheader(
// MOsrValue instructions are infallible, so the first MResumePoint must
// occur after they execute, at the point of the MStart.
MOZ_TRY(resumeAt(start, loopEntry));
MOZ_TRY(resumeAt(start, loopHead));
// Link the same MResumePoint from the MStart to each MOsrValue.
// This causes logic in ShouldSpecializeInput() to not replace Uses with
......@@ -7972,8 +7974,8 @@ static bool ObjectHasExtraOwnProperty(CompileRealm* realm,
return ClassMayResolveId(realm->runtime()->names(), clasp, id, singleton);
}
void IonBuilder::insertRecompileCheck() {
MOZ_ASSERT(pc == script()->code() || *pc == JSOP_LOOPENTRY);
void IonBuilder::insertRecompileCheck(jsbytecode* pc) {
MOZ_ASSERT(pc == script()->code() || *pc == JSOP_LOOPHEAD);
// No need for recompile checks if this is the highest optimization level or
// if we're performing an analysis instead of compilation.
......@@ -7988,7 +7990,7 @@ void IonBuilder::insertRecompileCheck() {
// works.
MRecompileCheck::RecompileCheckType type;
if (*pc == JSOP_LOOPENTRY) {
if (*pc == JSOP_LOOPHEAD) {
type = MRecompileCheck::RecompileCheckType::OptimizationLevelOSR;
} else if (this != outermostBuilder()) {
type = MRecompileCheck::RecompileCheckType::OptimizationLevelInlined;
......
......@@ -238,7 +238,7 @@ class IonBuilder : public MIRGenerator,
MBasicBlock* at, size_t stackDepth, jsbytecode* pc,
MBasicBlock* maybePredecessor = nullptr);
AbortReasonOr<MBasicBlock*> newOsrPreheader(MBasicBlock* header,
jsbytecode* loopEntry);
jsbytecode* loopHead);
AbortReasonOr<MBasicBlock*> newPendingLoopHeader(MBasicBlock* predecessor,
jsbytecode* pc, bool osr,
bool canOsr,
......@@ -278,6 +278,8 @@ class IonBuilder : public MIRGenerator,
TemporaryTypeSet* typeSet);
AbortReasonOr<Ok> maybeAddOsrTypeBarriers();
AbortReasonOr<Ok> emitLoopHeadInstructions(jsbytecode* pc);
// Restarts processing of a loop if the type information at its header was
// incomplete.
AbortReasonOr<Ok> restartLoop(MBasicBlock* header);
......@@ -290,7 +292,7 @@ class IonBuilder : public MIRGenerator,
AbortReasonOr<Ok> resumeAfter(MInstruction* ins);
AbortReasonOr<Ok> maybeInsertResume();
void insertRecompileCheck();
void insertRecompileCheck(jsbytecode* pc);
bool usesEnvironmentChain();
......@@ -729,7 +731,6 @@ class IonBuilder : public MIRGenerator,
AbortReasonOr<Ok> jsop_andor(JSOp op);
AbortReasonOr<Ok> jsop_dup2();
AbortReasonOr<Ok> jsop_goto(bool* restarted);
AbortReasonOr<Ok> jsop_loopentry(bool* restarted);
AbortReasonOr<Ok> jsop_loophead(jsbytecode* pc);
AbortReasonOr<Ok> jsop_compare(JSOp op);
AbortReasonOr<Ok> jsop_compare(JSOp op, MDefinition* left,
......
......@@ -80,7 +80,7 @@ void OptimizationInfo::initWasmOptimizationInfo() {
uint32_t OptimizationInfo::compilerWarmUpThreshold(JSScript* script,
jsbytecode* pc) const {
MOZ_ASSERT(pc == nullptr || pc == script->code() ||
JSOp(*pc) == JSOP_LOOPENTRY);
JSOp(*pc) == JSOP_LOOPHEAD);
if (pc == script->code()) {
pc = nullptr;
......@@ -111,17 +111,17 @@ uint32_t OptimizationInfo::compilerWarmUpThreshold(JSScript* script,
// It's more efficient to enter outer loops, rather than inner loops, via OSR.
// To accomplish this, we use a slightly higher threshold for inner loops.
// Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
uint32_t loopDepth = LoopEntryDepthHint(pc);
uint32_t loopDepth = LoopHeadDepthHint(pc);
MOZ_ASSERT(loopDepth > 0);
return warmUpThreshold + loopDepth * (baseCompilerWarmUpThreshold() / 10);
}
uint32_t OptimizationInfo::recompileWarmUpThreshold(JSScript* script,
jsbytecode* pc) const {
MOZ_ASSERT(pc == script->code() || *pc == JSOP_LOOPENTRY);
MOZ_ASSERT(pc == script->code() || *pc == JSOP_LOOPHEAD);
uint32_t threshold = compilerWarmUpThreshold(script, pc);
if (*pc != JSOP_LOOPENTRY || JitOptions.eagerIonCompilation()) {
if (*pc != JSOP_LOOPHEAD || JitOptions.eagerIonCompilation()) {
return threshold;
}
......@@ -131,7 +131,7 @@ uint32_t OptimizationInfo::recompileWarmUpThreshold(JSScript* script,
// avoid invalidation completely). Use a very high recompilation threshold for
// loop edges so that this only affects very long-running loops.
uint32_t loopDepth = LoopEntryDepthHint(pc);
uint32_t loopDepth = LoopHeadDepthHint(pc);
MOZ_ASSERT(loopDepth > 0);
return threshold + loopDepth * (baseCompilerWarmUpThreshold() / 10);
}
......
......@@ -1580,9 +1580,9 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
}
break;
case JOF_LOOPENTRY:
case JOF_LOOPHEAD:
if (!sp->jsprintf(" (ic: %u, data: %u,%u)", GET_ICINDEX(pc),
LoopEntryCanIonOsr(pc), LoopEntryDepthHint(pc))) {
LoopHeadCanIonOsr(pc), LoopHeadDepthHint(pc))) {
return 0;
}
break;
......
......@@ -40,28 +40,28 @@ enum JSOp : uint8_t {
* [SMDOC] Bytecode Format flags (JOF_*)
*/
enum {
JOF_BYTE = 0, /* single bytecode, no immediates */
JOF_UINT8 = 1, /* unspecified uint8_t argument */
JOF_UINT16 = 2, /* unspecified uint16_t argument */
JOF_UINT24 = 3, /* unspecified uint24_t argument */
JOF_UINT32 = 4, /* unspecified uint32_t argument */
JOF_INT8 = 5, /* int8_t literal */
JOF_INT32 = 6, /* int32_t literal */
JOF_JUMP = 7, /* int32_t jump offset */
JOF_TABLESWITCH = 8, /* table switch */
JOF_ENVCOORD = 9, /* embedded ScopeCoordinate immediate */
JOF_ARGC = 10, /* uint16_t argument count */
JOF_QARG = 11, /* function argument index */
JOF_LOCAL = 12, /* var or block-local variable */
JOF_RESUMEINDEX = 13, /* yield, await, or gosub resume index */
JOF_ATOM = 14, /* uint32_t constant index */
JOF_OBJECT = 15, /* uint32_t object index */
JOF_REGEXP = 16, /* uint32_t regexp index */
JOF_DOUBLE = 17, /* inline DoubleValue */
JOF_SCOPE = 18, /* uint32_t scope index */
JOF_ICINDEX = 19, /* uint32_t IC index */
JOF_LOOPENTRY = 20, /* JSOP_LOOPENTRY, combines JOF_ICINDEX and JOF_UINT8 */