Bug 1382973 part 2 - Eliminate some BytecodeAnalysis::maybeInfo checks in IonBuilder. r=nbp

This commit is contained in:
Jan de Mooij 2017-07-22 14:21:52 +02:00
Родитель e2a6ce0202
Коммит fcbb532c3e
5 изменённых файлов: 68 добавлений и 33 удалений

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

@ -281,9 +281,14 @@ BaselineInspector::monomorphicStub(jsbytecode* pc)
if (!hasBaselineScript())
return nullptr;
const ICEntry& entry = icEntryFromPC(pc);
// IonBuilder::analyzeNewLoopTypes may call this (via expectedResultType
// below) on code that's unreachable, according to BytecodeAnalysis. Use
// maybeICEntryFromPC to handle this.
const ICEntry* entry = maybeICEntryFromPC(pc);
if (!entry)
return nullptr;
ICStub* stub = entry.firstStub();
ICStub* stub = entry->firstStub();
ICStub* next = stub->next();
if (!next || !next->isFallback())
@ -316,7 +321,9 @@ MIRType
BaselineInspector::expectedResultType(jsbytecode* pc)
{
// Look at the IC entries for this op to guess what type it will produce,
// returning MIRType::None otherwise.
// returning MIRType::None otherwise. Note that IonBuilder may call this
// for bytecode ops that are unreachable and don't have a Baseline IC, see
// comment in monomorphicStub.
ICStub* stub = monomorphicStub(pc);
if (!stub)

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

@ -77,6 +77,18 @@ class BaselineInspector
return ent;
}
BaselineICEntry* maybeICEntryFromPC(jsbytecode* pc) {
MOZ_ASSERT(hasBaselineScript());
MOZ_ASSERT(isValidPC(pc));
BaselineICEntry* ent =
baselineScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc), prevLookedUpEntry);
if (!ent)
return nullptr;
MOZ_ASSERT(ent->isForOp());
prevLookedUpEntry = ent;
return ent;
}
template <typename ICInspectorType>
ICInspectorType makeICInspector(jsbytecode* pc, ICStub::Kind expectedFallbackKind) {
BaselineICEntry* ent = nullptr;

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

@ -645,21 +645,19 @@ BaselineScript::icEntryFromReturnOffset(CodeOffset returnOffset)
return icEntry(loc);
}
static inline size_t
ComputeBinarySearchMid(BaselineScript* baseline, uint32_t pcOffset)
static inline bool
ComputeBinarySearchMid(BaselineScript* baseline, uint32_t pcOffset, size_t* loc)
{
size_t loc;
BinarySearchIf(ICEntries(baseline), 0, baseline->numICEntries(),
[pcOffset](BaselineICEntry& entry) {
uint32_t entryOffset = entry.pcOffset();
if (pcOffset < entryOffset)
return -1;
if (entryOffset < pcOffset)
return 1;
return 0;
},
&loc);
return loc;
return BinarySearchIf(ICEntries(baseline), 0, baseline->numICEntries(),
[pcOffset](BaselineICEntry& entry) {
uint32_t entryOffset = entry.pcOffset();
if (pcOffset < entryOffset)
return -1;
if (entryOffset < pcOffset)
return 1;
return 0;
},
loc);
}
uint8_t*
@ -668,29 +666,39 @@ BaselineScript::returnAddressForIC(const BaselineICEntry& ent)
return method()->raw() + ent.returnOffset().offset();
}
BaselineICEntry&
BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
BaselineICEntry*
BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset)
{
// Multiple IC entries can have the same PC offset, but this method only looks for
// those which have isForOp() set.
size_t mid = ComputeBinarySearchMid(this, pcOffset);
size_t mid;
if (!ComputeBinarySearchMid(this, pcOffset, &mid))
return nullptr;
// Found an IC entry with a matching PC offset. Search backward, and then
// forward from this IC entry, looking for one with the same PC offset which
// has isForOp() set.
for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) {
if (icEntry(i).isForOp())
return icEntry(i);
return &icEntry(i);
}
for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) {
if (icEntry(i).isForOp())
return icEntry(i);
return &icEntry(i);
}
MOZ_CRASH("Invalid PC offset for IC entry.");
return nullptr;
}
BaselineICEntry&
BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry)
BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
{
BaselineICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
BaselineICEntry*
BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry)
{
// Do a linear forward search from the last queried PC offset, or fallback to a
// binary search if the last offset is too far away.
@ -702,14 +710,21 @@ BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLook
BaselineICEntry* curEntry = prevLookedUpEntry;
while (curEntry >= firstEntry && curEntry <= lastEntry) {
if (curEntry->pcOffset() == pcOffset && curEntry->isForOp())
break;
return curEntry;
curEntry++;
}
MOZ_ASSERT(curEntry->pcOffset() == pcOffset && curEntry->isForOp());
return *curEntry;
return nullptr;
}
return icEntryFromPCOffset(pcOffset);
return maybeICEntryFromPCOffset(pcOffset);
}
BaselineICEntry&
BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry)
{
BaselineICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
BaselineICEntry&
@ -717,7 +732,8 @@ BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset)
{
// Like icEntryFromPCOffset, but only looks for the fake ICEntries
// inserted by VM calls.
size_t mid = ComputeBinarySearchMid(this, pcOffset);
size_t mid;
MOZ_ALWAYS_TRUE(ComputeBinarySearchMid(this, pcOffset, &mid));
for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) {
if (icEntry(i).kind() == ICEntry::Kind_CallVM)

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

@ -379,6 +379,10 @@ struct BaselineScript
return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
}
BaselineICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
BaselineICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
BaselineICEntry* prevLookedUpEntry);
BaselineICEntry& icEntry(size_t index);
BaselineICEntry& icEntryFromReturnOffset(CodeOffset returnOffset);
BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset);

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

@ -583,8 +583,6 @@ IonBuilder::analyzeNewLoopTypes(const CFGBlock* loopEntryBlock)
continue;
if (slot >= info().firstStackSlot())
continue;
if (!analysis().maybeInfo(pc))
continue;
if (!last)
continue;
@ -1760,8 +1758,6 @@ IonBuilder::visitControlInstruction(CFGControlInstruction* ins, bool* restarted)
AbortReasonOr<Ok>
IonBuilder::inspectOpcode(JSOp op)
{
MOZ_ASSERT(analysis_.maybeInfo(pc), "Compiling unreachable op");
// Add not yet implemented opcodes at the bottom of the switch!
switch (op) {
case JSOP_NOP: