closes #376: M1329901 M1330667 M1342016 (modified) M1304081 M1259476

This commit is contained in:
Cameron Kaiser 2018-07-06 17:27:11 -07:00
parent 1fe2d3921c
commit 8a97adc59a
10 changed files with 166 additions and 49 deletions

View File

@ -0,0 +1,17 @@
/* This is supposed to be jit-test --ion-pgo=on */
try {
x = evalcx('');
x.__proto__ = 0;
} catch (e) {}
(function() {
for (var i = 0; i < 1; ++i) {
if (i % 5 == 0) {
for (let z of[0, 0, new Boolean(false), new Boolean(false),
new Boolean(false), new Boolean(false)]) {
this.x;
}
}
}
})()

View File

@ -391,6 +391,9 @@ BacktrackingAllocator::init()
LBlock* block = graph.getBlock(i); LBlock* block = graph.getBlock(i);
for (LInstructionIterator ins = block->begin(); ins != block->end(); ins++) { for (LInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
if (mir->shouldCancel("Create data structures (inner loop 1)"))
return false;
for (size_t j = 0; j < ins->numDefs(); j++) { for (size_t j = 0; j < ins->numDefs(); j++) {
LDefinition* def = ins->getDef(j); LDefinition* def = ins->getDef(j);
if (def->isBogusTemp()) if (def->isBogusTemp())
@ -828,7 +831,7 @@ BacktrackingAllocator::go()
return false; return false;
QueueItem item = allocationQueue.removeHighest(); QueueItem item = allocationQueue.removeHighest();
if (!processBundle(item.bundle)) if (!processBundle(mir, item.bundle))
return false; return false;
} }
JitSpew(JitSpew_RegAlloc, "Main allocation loop complete"); JitSpew(JitSpew_RegAlloc, "Main allocation loop complete");
@ -1221,7 +1224,7 @@ BacktrackingAllocator::tryAllocateNonFixed(LiveBundle* bundle,
} }
bool bool
BacktrackingAllocator::processBundle(LiveBundle* bundle) BacktrackingAllocator::processBundle(MIRGenerator* mir, LiveBundle* bundle)
{ {
if (JitSpewEnabled(JitSpew_RegAlloc)) { if (JitSpewEnabled(JitSpew_RegAlloc)) {
JitSpew(JitSpew_RegAlloc, "Allocating %s [priority %lu] [weight %lu]", JitSpew(JitSpew_RegAlloc, "Allocating %s [priority %lu] [weight %lu]",
@ -1256,6 +1259,9 @@ BacktrackingAllocator::processBundle(LiveBundle* bundle)
bool fixed; bool fixed;
LiveBundleVector conflicting; LiveBundleVector conflicting;
for (size_t attempt = 0;; attempt++) { for (size_t attempt = 0;; attempt++) {
if (mir->shouldCancel("Backtracking Allocation (processBundle loop)"))
return false;
if (canAllocate) { if (canAllocate) {
bool success = false; bool success = false;
fixed = false; fixed = false;
@ -1719,7 +1725,7 @@ BacktrackingAllocator::resolveControlFlow()
for (size_t i = 1; i < graph.numVirtualRegisters(); i++) { for (size_t i = 1; i < graph.numVirtualRegisters(); i++) {
VirtualRegister& reg = vregs[i]; VirtualRegister& reg = vregs[i];
if (mir->shouldCancel("Backtracking Resolve Control Flow (vreg loop)")) if (mir->shouldCancel("Backtracking Resolve Control Flow (vreg outer loop)"))
return false; return false;
if (!alloc().ensureBallast()) if (!alloc().ensureBallast())
@ -1728,6 +1734,9 @@ BacktrackingAllocator::resolveControlFlow()
for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; ) { for (LiveRange::RegisterLinkIterator iter = reg.rangesBegin(); iter; ) {
LiveRange* range = LiveRange::get(*iter); LiveRange* range = LiveRange::get(*iter);
if (mir->shouldCancel("Backtracking Resolve Control Flow (vreg inner loop)"))
return false;
// Remove ranges which will never be used. // Remove ranges which will never be used.
if (deadRange(range)) { if (deadRange(range)) {
reg.removeRangeAndIncrement(iter); reg.removeRangeAndIncrement(iter);

View File

@ -663,7 +663,7 @@ class BacktrackingAllocator : protected RegisterAllocator
bool* success, bool* pfixed, LiveBundleVector& conflicting); bool* success, bool* pfixed, LiveBundleVector& conflicting);
bool tryAllocateNonFixed(LiveBundle* bundle, Requirement requirement, Requirement hint, bool tryAllocateNonFixed(LiveBundle* bundle, Requirement requirement, Requirement hint,
bool* success, bool* pfixed, LiveBundleVector& conflicting); bool* success, bool* pfixed, LiveBundleVector& conflicting);
bool processBundle(LiveBundle* bundle); bool processBundle(MIRGenerator* mir, LiveBundle* bundle);
bool computeRequirement(LiveBundle* bundle, Requirement *prequirement, Requirement *phint); bool computeRequirement(LiveBundle* bundle, Requirement *prequirement, Requirement *phint);
bool tryAllocateRegister(PhysicalRegister& r, LiveBundle* bundle, bool tryAllocateRegister(PhysicalRegister& r, LiveBundle* bundle,
bool* success, bool* pfixed, LiveBundleVector& conflicting); bool* success, bool* pfixed, LiveBundleVector& conflicting);

View File

@ -480,6 +480,7 @@ class CompileInfo
// the frame is active on the stack. This implies that these definitions // the frame is active on the stack. This implies that these definitions
// would have to be executed and that they cannot be removed even if they // would have to be executed and that they cannot be removed even if they
// are unused. // are unused.
#if(0)
bool isObservableSlot(uint32_t slot) const { bool isObservableSlot(uint32_t slot) const {
if (isObservableFrameSlot(slot)) if (isObservableFrameSlot(slot))
return true; return true;
@ -489,6 +490,17 @@ class CompileInfo
return false; return false;
} }
#else // bug 1342016 attachment 8849618 for our older code
inline bool isObservableSlot(uint32_t slot) const {
if (slot >= firstLocalSlot())
return false;
if (slot < firstArgSlot())
return isObservableFrameSlot(slot);
return isObservableArgumentSlot(slot);
}
#endif
bool isObservableFrameSlot(uint32_t slot) const { bool isObservableFrameSlot(uint32_t slot) const {
if (!funMaybeLazy()) if (!funMaybeLazy())

View File

@ -24,9 +24,10 @@ EdgeCaseAnalysis::analyzeLate()
uint32_t nextId = 0; uint32_t nextId = 0;
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
if (mir->shouldCancel("Analyze Late (first loop)"))
return false;
for (MDefinitionIterator iter(*block); iter; iter++) { for (MDefinitionIterator iter(*block); iter; iter++) {
if (mir->shouldCancel("Analyze Late (first loop)"))
return false;
iter->setId(nextId++); iter->setId(nextId++);
iter->analyzeEdgeCasesForward(); iter->analyzeEdgeCasesForward();
} }
@ -34,10 +35,12 @@ EdgeCaseAnalysis::analyzeLate()
} }
for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) { for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
if (mir->shouldCancel("Analyze Late (second loop)")) for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++) {
return false; if (mir->shouldCancel("Analyze Late (second loop)"))
for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++) return false;
riter->analyzeEdgeCasesBackward(); riter->analyzeEdgeCasesBackward();
}
} }
return true; return true;

View File

@ -1506,17 +1506,20 @@ OptimizeMIR(MIRGenerator* mir)
else else
logger = TraceLoggerForCurrentThread(); logger = TraceLoggerForCurrentThread();
if (mir->shouldCancel("Start"))
return false;
if (!mir->compilingAsmJS()) { if (!mir->compilingAsmJS()) {
if (!MakeMRegExpHoistable(graph)) if (!MakeMRegExpHoistable(mir, graph))
return false;
if (mir->shouldCancel("Make MRegExp Hoistable"))
return false; return false;
} }
gs.spewPass("BuildSSA"); gs.spewPass("BuildSSA");
AssertBasicGraphCoherency(graph); AssertBasicGraphCoherency(graph);
if (mir->shouldCancel("Start"))
return false;
if (!JitOptions.disablePgo && !mir->compilingAsmJS()) { if (!JitOptions.disablePgo && !mir->compilingAsmJS()) {
AutoTraceLog log(logger, TraceLogger_PruneUnusedBranches); AutoTraceLog log(logger, TraceLogger_PruneUnusedBranches);
if (!PruneUnusedBranches(mir, graph)) if (!PruneUnusedBranches(mir, graph))

View File

@ -30,7 +30,8 @@ using mozilla::DebugOnly;
typedef Vector<MPhi*, 16, SystemAllocPolicy> MPhiVector; typedef Vector<MPhi*, 16, SystemAllocPolicy> MPhiVector;
static bool static bool
FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVector& worklist) FlagPhiInputsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block, MBasicBlock* succ,
MPhiVector& worklist)
{ {
// When removing an edge between 2 blocks, we might remove the ability of // When removing an edge between 2 blocks, we might remove the ability of
// later phases to figure out that the uses of a Phi should be considered as // later phases to figure out that the uses of a Phi should be considered as
@ -103,6 +104,9 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
for (; it != end; it++) { for (; it != end; it++) {
MPhi* phi = *it; MPhi* phi = *it;
if (mir->shouldCancel("FlagPhiInputsAsHavingRemovedUses outer loop"))
return false;
// We are looking to mark the Phi inputs which are used across the edge // We are looking to mark the Phi inputs which are used across the edge
// between the |block| and its successor |succ|. // between the |block| and its successor |succ|.
MDefinition* def = phi->getOperand(predIndex); MDefinition* def = phi->getOperand(predIndex);
@ -120,9 +124,23 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
bool isUsed = false; bool isUsed = false;
for (size_t idx = 0; !isUsed && idx < worklist.length(); idx++) { for (size_t idx = 0; !isUsed && idx < worklist.length(); idx++) {
phi = worklist[idx]; phi = worklist[idx];
if (mir->shouldCancel("FlagPhiInputsAsHavingRemovedUses inner loop 1"))
return false;
if (phi->isUseRemoved() || phi->isImplicitlyUsed()) {
// The phi is implicitly used.
isUsed = true;
break;
}
MUseIterator usesEnd(phi->usesEnd()); MUseIterator usesEnd(phi->usesEnd());
for (MUseIterator use(phi->usesBegin()); use != usesEnd; use++) { for (MUseIterator use(phi->usesBegin()); use != usesEnd; use++) {
MNode* consumer = (*use)->consumer(); MNode* consumer = (*use)->consumer();
if (mir->shouldCancel("FlagPhiInputsAsHavingRemovedUses inner loop 2"))
return false;
if (consumer->isResumePoint()) { if (consumer->isResumePoint()) {
MResumePoint* rp = consumer->toResumePoint(); MResumePoint* rp = consumer->toResumePoint();
if (rp->isObservableOperand(*use)) { if (rp->isObservableOperand(*use)) {
@ -144,12 +162,6 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
if (phi->isInWorklist()) if (phi->isInWorklist())
continue; continue;
if (phi->isUseRemoved() || phi->isImplicitlyUsed()) {
// The phi is implicitly used.
isUsed = true;
break;
}
phi->setInWorklist(); phi->setInWorklist();
if (!worklist.append(phi)) if (!worklist.append(phi))
return false; return false;
@ -177,11 +189,16 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
} }
static bool static bool
FlagAllOperandsAsHavingRemovedUses(MBasicBlock* block) FlagAllOperandsAsHavingRemovedUses(MIRGenerator* mir, MBasicBlock* block)
{ {
const CompileInfo& info = block->info();
// Flag all instructions operands as having removed uses. // Flag all instructions operands as having removed uses.
MInstructionIterator end = block->end(); MInstructionIterator end = block->end();
for (MInstructionIterator it = block->begin(); it != end; it++) { for (MInstructionIterator it = block->begin(); it != end; it++) {
if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses loop 1"))
return false;
MInstruction* ins = *it; MInstruction* ins = *it;
for (size_t i = 0, e = ins->numOperands(); i < e; i++) for (size_t i = 0, e = ins->numOperands(); i < e; i++)
ins->getOperand(i)->setUseRemovedUnchecked(); ins->getOperand(i)->setUseRemovedUnchecked();
@ -191,9 +208,17 @@ FlagAllOperandsAsHavingRemovedUses(MBasicBlock* block)
// Note: no need to iterate over the caller's of the resume point as // Note: no need to iterate over the caller's of the resume point as
// this is the same as the entry resume point. // this is the same as the entry resume point.
for (size_t i = 0, e = rp->numOperands(); i < e; i++) { for (size_t i = 0, e = rp->numOperands(); i < e; i++) {
#if(0) // bug 1329901, bug 1342016
if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses inner loop"))
return false;
if (!rp->isObservableOperand(i)) if (!rp->isObservableOperand(i))
continue; continue;
rp->getOperand(i)->setUseRemovedUnchecked(); rp->getOperand(i)->setUseRemovedUnchecked();
#else
if (info.isObservableSlot(i))
rp->getOperand(i)->setUseRemovedUnchecked();
#endif
} }
} }
} }
@ -201,10 +226,18 @@ FlagAllOperandsAsHavingRemovedUses(MBasicBlock* block)
// Flag observable operands of the entry resume point as having removed uses. // Flag observable operands of the entry resume point as having removed uses.
MResumePoint* rp = block->entryResumePoint(); MResumePoint* rp = block->entryResumePoint();
while (rp) { while (rp) {
if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses loop 2"))
return false;
for (size_t i = 0, e = rp->numOperands(); i < e; i++) { for (size_t i = 0, e = rp->numOperands(); i < e; i++) {
#if(0) // bug 1329901, bug 1342016
if (!rp->isObservableOperand(i)) if (!rp->isObservableOperand(i))
continue; continue;
rp->getOperand(i)->setUseRemovedUnchecked(); rp->getOperand(i)->setUseRemovedUnchecked();
#else
if (info.isObservableSlot(i))
rp->getOperand(i)->setUseRemovedUnchecked();
#endif
} }
rp = rp->caller(); rp = rp->caller();
} }
@ -212,7 +245,10 @@ FlagAllOperandsAsHavingRemovedUses(MBasicBlock* block)
// Flag Phi inputs of the successors has having removed uses. // Flag Phi inputs of the successors has having removed uses.
MPhiVector worklist; MPhiVector worklist;
for (size_t i = 0, e = block->numSuccessors(); i < e; i++) { for (size_t i = 0, e = block->numSuccessors(); i < e; i++) {
if (!FlagPhiInputsAsHavingRemovedUses(block, block->getSuccessor(i), worklist)) if (mir->shouldCancel("FlagAllOperandsAsHavingRemovedUses loop 3"))
return false;
if (!FlagPhiInputsAsHavingRemovedUses(mir, block, block->getSuccessor(i), worklist))
return false; return false;
} }
@ -261,6 +297,9 @@ jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph)
// unreachable if all predecessors are flagged as bailing or unreachable. // unreachable if all predecessors are flagged as bailing or unreachable.
bool someUnreachable = false; bool someUnreachable = false;
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
if (mir->shouldCancel("Prune unused branches (main loop)"))
return false;
JitSpew(JitSpew_Prune, "Investigate Block %d:", block->id()); JitSpew(JitSpew_Prune, "Investigate Block %d:", block->id());
// Do not touch entry basic blocks. // Do not touch entry basic blocks.
@ -274,6 +313,9 @@ jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph)
size_t numPred = block->numPredecessors(); size_t numPred = block->numPredecessors();
size_t i = 0; size_t i = 0;
for (; i < numPred; i++) { for (; i < numPred; i++) {
if (mir->shouldCancel("Prune unused branches (inner loop 1)"))
return false;
MBasicBlock* pred = block->getPredecessor(i); MBasicBlock* pred = block->getPredecessor(i);
// The backedge is visited after the loop header, but if the loop // The backedge is visited after the loop header, but if the loop
@ -304,6 +346,9 @@ jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph)
size_t predCount = 0; size_t predCount = 0;
bool isLoopExit = false; bool isLoopExit = false;
while (p--) { while (p--) {
if (mir->shouldCancel("Prune unused branches (inner loop 2)"))
return false;
MBasicBlock* pred = block->getPredecessor(p); MBasicBlock* pred = block->getPredecessor(p);
if (pred->getHitState() == MBasicBlock::HitState::Count) if (pred->getHitState() == MBasicBlock::HitState::Count)
predCount += pred->getHitCount(); predCount += pred->getHitCount();
@ -369,16 +414,22 @@ jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph)
// As we are going to remove edges and basic block, we have to mark // As we are going to remove edges and basic block, we have to mark
// instructions which would be needed by baseline if we were to bailout. // instructions which would be needed by baseline if we were to bailout.
for (PostorderIterator it(graph.poBegin()); it != graph.poEnd();) { for (PostorderIterator it(graph.poBegin()); it != graph.poEnd();) {
if (mir->shouldCancel("Prune unused branches (marking loop)"))
return false;
MBasicBlock* block = *it++; MBasicBlock* block = *it++;
if (!block->isMarked() && !block->unreachable()) if (!block->isMarked() && !block->unreachable())
continue; continue;
FlagAllOperandsAsHavingRemovedUses(block); FlagAllOperandsAsHavingRemovedUses(mir, block);
} }
// Remove the blocks in post-order such that consumers are visited before // Remove the blocks in post-order such that consumers are visited before
// the predecessors, the only exception being the Phi nodes of loop headers. // the predecessors, the only exception being the Phi nodes of loop headers.
for (PostorderIterator it(graph.poBegin()); it != graph.poEnd();) { for (PostorderIterator it(graph.poBegin()); it != graph.poEnd();) {
if (mir->shouldCancel("Prune unused branches (removal loop)"))
return false;
MBasicBlock* block = *it++; MBasicBlock* block = *it++;
if (!block->isMarked() && !block->unreachable()) if (!block->isMarked() && !block->unreachable())
continue; continue;
@ -1071,13 +1122,13 @@ jit::EliminatePhis(MIRGenerator* mir, MIRGraph& graph,
// Add all observable phis to a worklist. We use the "in worklist" bit to // Add all observable phis to a worklist. We use the "in worklist" bit to
// mean "this phi is live". // mean "this phi is live".
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) { for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
if (mir->shouldCancel("Eliminate Phis (populate loop)"))
return false;
MPhiIterator iter = block->phisBegin(); MPhiIterator iter = block->phisBegin();
while (iter != block->phisEnd()) { while (iter != block->phisEnd()) {
MPhi* phi = *iter++; MPhi* phi = *iter++;
if (mir->shouldCancel("Eliminate Phis (populate loop)"))
return false;
// Flag all as unused, only observable phis would be marked as used // Flag all as unused, only observable phis would be marked as used
// when processed by the work list. // when processed by the work list.
phi->setUnused(); phi->setUnused();
@ -1357,6 +1408,9 @@ TypeAnalyzer::specializePhis()
return false; return false;
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) { for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
if (mir->shouldCancel("Specialize Phis (inner loop)"))
return false;
bool hasInputsWithEmptyTypes; bool hasInputsWithEmptyTypes;
MIRType type = GuessPhiType(*phi, &hasInputsWithEmptyTypes); MIRType type = GuessPhiType(*phi, &hasInputsWithEmptyTypes);
phi->specialize(type); phi->specialize(type);
@ -1739,10 +1793,10 @@ bool
TypeAnalyzer::graphContainsFloat32() TypeAnalyzer::graphContainsFloat32()
{ {
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); ++block) { for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); ++block) {
if (mir->shouldCancel("Ensure Float32 commutativity - Graph contains Float32"))
return false;
for (MDefinitionIterator def(*block); def; def++) { for (MDefinitionIterator def(*block); def; def++) {
if (mir->shouldCancel("Ensure Float32 commutativity - Graph contains Float32"))
return false;
if (def->type() == MIRType_Float32) if (def->type() == MIRType_Float32)
return true; return true;
} }
@ -1822,7 +1876,7 @@ jit::ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph)
} }
bool bool
jit::MakeMRegExpHoistable(MIRGraph& graph) jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph)
{ {
// If we are compiling try blocks, regular expressions may be observable // If we are compiling try blocks, regular expressions may be observable
// from catch blocks (which Ion does not compile). For now just disable the // from catch blocks (which Ion does not compile). For now just disable the
@ -1831,7 +1885,13 @@ jit::MakeMRegExpHoistable(MIRGraph& graph)
return true; return true;
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
if (mir->shouldCancel("MakeMRegExpHoistable outer loop"))
return false;
for (MDefinitionIterator iter(*block); iter; iter++) { for (MDefinitionIterator iter(*block); iter; iter++) {
if (mir->shouldCancel("MakeMRegExpHoistable inner loop"))
return false;
if (!iter->isRegExp()) if (!iter->isRegExp())
continue; continue;
@ -1840,6 +1900,9 @@ jit::MakeMRegExpHoistable(MIRGraph& graph)
// Test if MRegExp is hoistable by looking at all uses. // Test if MRegExp is hoistable by looking at all uses.
bool hoistable = true; bool hoistable = true;
for (MUseIterator i = regexp->usesBegin(); i != regexp->usesEnd(); i++) { for (MUseIterator i = regexp->usesBegin(); i != regexp->usesEnd(); i++) {
if (mir->shouldCancel("IsRegExpHoistable inner loop"))
return false;
// Ignore resume points. At this point all uses are listed. // Ignore resume points. At this point all uses are listed.
// No DCE or GVN or something has happened. // No DCE or GVN or something has happened.
if (i->consumer()->isResumePoint()) if (i->consumer()->isResumePoint())
@ -1939,7 +2002,7 @@ jit::RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph, uint32_t numMarked
if (!block->isMarked()) if (!block->isMarked())
continue; continue;
FlagAllOperandsAsHavingRemovedUses(block); FlagAllOperandsAsHavingRemovedUses(mir, block);
} }
// Find unmarked blocks and remove them. // Find unmarked blocks and remove them.

View File

@ -54,7 +54,7 @@ bool
ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph); ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph);
bool bool
MakeMRegExpHoistable(MIRGraph& graph); MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph);
bool bool
RenumberBlocks(MIRGraph& graph); RenumberBlocks(MIRGraph& graph);

View File

@ -158,7 +158,9 @@ IonBuilder::IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
failedShapeGuard_(info->script()->failedShapeGuard()), failedShapeGuard_(info->script()->failedShapeGuard()),
failedLexicalCheck_(info->script()->failedLexicalCheck()), failedLexicalCheck_(info->script()->failedLexicalCheck()),
nonStringIteration_(false), nonStringIteration_(false),
lazyArguments_(nullptr), #ifdef DEBUG
hasLazyArguments_(false),
#endif
inlineCallInfo_(nullptr), inlineCallInfo_(nullptr),
maybeFallbackFunctionGetter_(nullptr) maybeFallbackFunctionGetter_(nullptr)
{ {
@ -908,11 +910,11 @@ IonBuilder::build()
ins->setResumePoint(entryRpCopy); ins->setResumePoint(entryRpCopy);
} }
#ifdef DEBUG
// lazyArguments should never be accessed in |argsObjAliasesFormals| scripts. // lazyArguments should never be accessed in |argsObjAliasesFormals| scripts.
if (info().hasArguments() && !info().argsObjAliasesFormals()) { if (info().hasArguments() && !info().argsObjAliasesFormals())
lazyArguments_ = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS)); hasLazyArguments_ = true;
current->add(lazyArguments_); #endif
}
insertRecompileCheck(); insertRecompileCheck();
@ -1080,10 +1082,10 @@ IonBuilder::buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoi
// +2 for the scope chain and |this|, maybe another +1 for arguments object slot. // +2 for the scope chain and |this|, maybe another +1 for arguments object slot.
MOZ_ASSERT(current->entryResumePoint()->stackDepth() == info().totalSlots()); MOZ_ASSERT(current->entryResumePoint()->stackDepth() == info().totalSlots());
if (script_->argumentsHasVarBinding()) { #ifdef DEBUG
lazyArguments_ = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS)); if (script_->argumentsHasVarBinding())
current->add(lazyArguments_); hasLazyArguments_ = true;
} #endif
insertRecompileCheck(); insertRecompileCheck();
@ -1349,10 +1351,14 @@ IonBuilder::addOsrValueTypeBarrier(uint32_t slot, MInstruction** def_,
} }
case MIRType_MagicOptimizedArguments: case MIRType_MagicOptimizedArguments:
MOZ_ASSERT(lazyArguments_); {
osrBlock->rewriteSlot(slot, lazyArguments_); MOZ_ASSERT(hasLazyArguments_);
def = lazyArguments_; MConstant* lazyArg = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS));
osrBlock->insertBefore(osrBlock->lastIns(), lazyArg);
osrBlock->rewriteSlot(slot, lazyArg);
def = lazyArg;
break; break;
}
default: default:
break; break;
@ -10195,8 +10201,11 @@ IonBuilder::jsop_arguments()
current->push(current->argumentsObject()); current->push(current->argumentsObject());
return true; return true;
} }
MOZ_ASSERT(lazyArguments_);
current->push(lazyArguments_); MOZ_ASSERT(hasLazyArguments_);
MConstant* lazyArg = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS));
current->add(lazyArg);
current->push(lazyArg);
return true; return true;
} }

View File

@ -1196,9 +1196,10 @@ class IonBuilder
// Has an iterator other than 'for in'. // Has an iterator other than 'for in'.
bool nonStringIteration_; bool nonStringIteration_;
// If this script can use a lazy arguments object, it will be pre-created #ifdef DEBUG
// here. // If this script uses the lazy arguments object.
MInstruction* lazyArguments_; bool hasLazyArguments_;
#endif
// If this is an inline builder, the call info for the builder. // If this is an inline builder, the call info for the builder.
const CallInfo* inlineCallInfo_; const CallInfo* inlineCallInfo_;