mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Allow canceling in-progress off thread ion compilations, bug 785761. r=dvander
This commit is contained in:
parent
d0b0ab5ea2
commit
d177fc87e2
@ -11,6 +11,7 @@
|
||||
#include "AliasAnalysis.h"
|
||||
#include "MIRGraph.h"
|
||||
#include "Ion.h"
|
||||
#include "IonBuilder.h"
|
||||
#include "IonSpewer.h"
|
||||
|
||||
using namespace js;
|
||||
@ -47,8 +48,9 @@ class AliasSetIterator
|
||||
}
|
||||
};
|
||||
|
||||
AliasAnalysis::AliasAnalysis(MIRGraph &graph)
|
||||
: graph_(graph),
|
||||
AliasAnalysis::AliasAnalysis(MIRGenerator *mir, MIRGraph &graph)
|
||||
: mir(mir),
|
||||
graph_(graph),
|
||||
loop_(NULL)
|
||||
{
|
||||
}
|
||||
@ -85,6 +87,9 @@ AliasAnalysis::analyze()
|
||||
uint32 newId = 1;
|
||||
|
||||
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
|
||||
if (mir->shouldCancel("Alias Analysis (main loop)"))
|
||||
return false;
|
||||
|
||||
if (block->isLoopHeader()) {
|
||||
IonSpew(IonSpew_Alias, "Processing loop header %d", block->id());
|
||||
loop_ = new LoopAliasInfo(loop_, *block);
|
||||
|
@ -55,11 +55,12 @@ class LoopAliasInfo : public TempObject {
|
||||
|
||||
class AliasAnalysis
|
||||
{
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph_;
|
||||
LoopAliasInfo *loop_;
|
||||
|
||||
public:
|
||||
AliasAnalysis(MIRGraph &graph);
|
||||
AliasAnalysis(MIRGenerator *mir, MIRGraph &graph);
|
||||
bool analyze();
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Ion.h"
|
||||
#include "IonBuilder.h"
|
||||
#include "IonSpewer.h"
|
||||
#include "EdgeCaseAnalysis.h"
|
||||
#include "MIR.h"
|
||||
@ -16,8 +17,8 @@
|
||||
using namespace js;
|
||||
using namespace js::ion;
|
||||
|
||||
EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGraph &graph)
|
||||
: graph(graph)
|
||||
EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph)
|
||||
: mir(mir), graph(graph)
|
||||
{
|
||||
}
|
||||
|
||||
@ -25,11 +26,15 @@ bool
|
||||
EdgeCaseAnalysis::analyzeLate()
|
||||
{
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
if (mir->shouldCancel("Analyze Late (first loop)"))
|
||||
return false;
|
||||
for (MDefinitionIterator iter(*block); iter; iter++)
|
||||
iter->analyzeEdgeCasesForward();
|
||||
}
|
||||
|
||||
for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
|
||||
if (mir->shouldCancel("Analyze Late (second loop)"))
|
||||
return false;
|
||||
for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
|
||||
riter->analyzeEdgeCasesBackward();
|
||||
}
|
||||
@ -42,6 +47,8 @@ EdgeCaseAnalysis::analyzeEarly()
|
||||
{
|
||||
|
||||
for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
|
||||
if (mir->shouldCancel("Analyze Early (main loop)"))
|
||||
return false;
|
||||
for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
|
||||
riter->analyzeTruncateBackward();
|
||||
}
|
||||
|
@ -15,10 +15,11 @@ class MIRGraph;
|
||||
|
||||
class EdgeCaseAnalysis
|
||||
{
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph;
|
||||
|
||||
public:
|
||||
EdgeCaseAnalysis(MIRGraph &graph);
|
||||
EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph);
|
||||
bool analyzeEarly();
|
||||
bool analyzeLate();
|
||||
static bool AllUsesTruncate(MInstruction *m);
|
||||
|
@ -765,60 +765,90 @@ CompileBackEnd(MIRGenerator *mir)
|
||||
|
||||
MIRGraph &graph = mir->graph();
|
||||
|
||||
if (mir->shouldCancel("Start"))
|
||||
return false;
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return NULL;
|
||||
IonSpewPass("Split Critical Edges");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Split Critical Edges"))
|
||||
return false;
|
||||
|
||||
if (!RenumberBlocks(graph))
|
||||
return NULL;
|
||||
IonSpewPass("Renumber Blocks");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Renumber Blocks"))
|
||||
return false;
|
||||
|
||||
if (!BuildDominatorTree(graph))
|
||||
return NULL;
|
||||
// No spew: graph not changed.
|
||||
|
||||
if (mir->shouldCancel("Dominator Tree"))
|
||||
return false;
|
||||
|
||||
// This must occur before any code elimination.
|
||||
if (!EliminatePhis(graph))
|
||||
if (!EliminatePhis(mir, graph))
|
||||
return NULL;
|
||||
IonSpewPass("Eliminate phis");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Eliminate phis"))
|
||||
return false;
|
||||
|
||||
if (!BuildPhiReverseMapping(graph))
|
||||
return NULL;
|
||||
// No spew: graph not changed.
|
||||
|
||||
if (mir->shouldCancel("Phi reverse mapping"))
|
||||
return false;
|
||||
|
||||
// This pass also removes copies.
|
||||
if (!ApplyTypeInformation(graph))
|
||||
if (!ApplyTypeInformation(mir, graph))
|
||||
return NULL;
|
||||
IonSpewPass("Apply types");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Apply types"))
|
||||
return false;
|
||||
|
||||
// Alias analysis is required for LICM and GVN so that we don't move
|
||||
// loads across stores.
|
||||
if (js_IonOptions.licm || js_IonOptions.gvn) {
|
||||
AliasAnalysis analysis(graph);
|
||||
AliasAnalysis analysis(mir, graph);
|
||||
if (!analysis.analyze())
|
||||
return NULL;
|
||||
IonSpewPass("Alias analysis");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Alias analysis"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js_IonOptions.edgeCaseAnalysis) {
|
||||
EdgeCaseAnalysis edgeCaseAnalysis(graph);
|
||||
EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
|
||||
if (!edgeCaseAnalysis.analyzeEarly())
|
||||
return NULL;
|
||||
IonSpewPass("Edge Case Analysis (Early)");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Edge Case Analysis (Early)"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js_IonOptions.gvn) {
|
||||
ValueNumberer gvn(graph, js_IonOptions.gvnIsOptimistic);
|
||||
ValueNumberer gvn(mir, graph, js_IonOptions.gvnIsOptimistic);
|
||||
if (!gvn.analyze())
|
||||
return NULL;
|
||||
IonSpewPass("GVN");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("GVN"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js_IonOptions.rangeAnalysis) {
|
||||
@ -828,36 +858,54 @@ CompileBackEnd(MIRGenerator *mir)
|
||||
IonSpewPass("Beta");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("RA Beta"))
|
||||
return false;
|
||||
|
||||
if (!r.analyze())
|
||||
return NULL;
|
||||
IonSpewPass("Range Analysis");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Range Analysis"))
|
||||
return false;
|
||||
|
||||
if (!r.removeBetaNobes())
|
||||
return NULL;
|
||||
IonSpewPass("De-Beta");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("RA De-Beta"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EliminateDeadCode(graph))
|
||||
if (!EliminateDeadCode(mir, graph))
|
||||
return NULL;
|
||||
IonSpewPass("DCE");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("DCE"))
|
||||
return false;
|
||||
|
||||
if (js_IonOptions.licm) {
|
||||
LICM licm(graph);
|
||||
LICM licm(mir, graph);
|
||||
if (!licm.analyze())
|
||||
return NULL;
|
||||
IonSpewPass("LICM");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("LICM"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js_IonOptions.edgeCaseAnalysis) {
|
||||
EdgeCaseAnalysis edgeCaseAnalysis(graph);
|
||||
EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
|
||||
if (!edgeCaseAnalysis.analyzeLate())
|
||||
return NULL;
|
||||
IonSpewPass("Edge Case Analysis (Late)");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Edge Case Analysis (Late)"))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: bounds check elimination has to run after all other passes that
|
||||
@ -869,6 +917,9 @@ CompileBackEnd(MIRGenerator *mir)
|
||||
IonSpewPass("Bounds Check Elimination");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Bounds Check Elimination"))
|
||||
return false;
|
||||
|
||||
LIRGraph *lir = mir->temp().lifoAlloc()->new_<LIRGraph>(&graph);
|
||||
if (!lir)
|
||||
return NULL;
|
||||
@ -878,11 +929,17 @@ CompileBackEnd(MIRGenerator *mir)
|
||||
return NULL;
|
||||
IonSpewPass("Generate LIR");
|
||||
|
||||
if (mir->shouldCancel("Generate LIR"))
|
||||
return false;
|
||||
|
||||
if (js_IonOptions.lsra) {
|
||||
LinearScanAllocator regalloc(&lirgen, *lir);
|
||||
LinearScanAllocator regalloc(mir, &lirgen, *lir);
|
||||
if (!regalloc.go())
|
||||
return NULL;
|
||||
IonSpewPass("Allocate Registers", ®alloc);
|
||||
|
||||
if (mir->shouldCancel("Allocate Registers"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return lir;
|
||||
|
@ -44,11 +44,14 @@ ion::SplitCriticalEdges(MIRGraph &graph)
|
||||
// This pass eliminates useless instructions.
|
||||
// The graph itself is unchanged.
|
||||
bool
|
||||
ion::EliminateDeadCode(MIRGraph &graph)
|
||||
ion::EliminateDeadCode(MIRGenerator *mir, MIRGraph &graph)
|
||||
{
|
||||
// Traverse in postorder so that we hit uses before definitions.
|
||||
// Traverse instruction list backwards for the same reason.
|
||||
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
|
||||
if (mir->shouldCancel("Eliminate Dead Code (main loop)"))
|
||||
return false;
|
||||
|
||||
// Remove unused instructions.
|
||||
for (MInstructionReverseIterator inst = block->rbegin(); inst != block->rend(); ) {
|
||||
if (!inst->isEffectful() && !inst->hasUses() && !inst->isGuard() &&
|
||||
@ -107,13 +110,16 @@ IsPhiRedundant(MPhi *phi)
|
||||
}
|
||||
|
||||
bool
|
||||
ion::EliminatePhis(MIRGraph &graph)
|
||||
ion::EliminatePhis(MIRGenerator *mir, MIRGraph &graph)
|
||||
{
|
||||
Vector<MPhi *, 16, SystemAllocPolicy> worklist;
|
||||
|
||||
// Add all observable phis to a worklist. We use the "in worklist" bit to
|
||||
// mean "this phi is live".
|
||||
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
|
||||
if (mir->shouldCancel("Eliminate Phis (populate loop)"))
|
||||
return false;
|
||||
|
||||
MPhiIterator iter = block->phisBegin();
|
||||
while (iter != block->phisEnd()) {
|
||||
// Flag all as unused, only observable phis would be marked as used
|
||||
@ -139,6 +145,9 @@ ion::EliminatePhis(MIRGraph &graph)
|
||||
|
||||
// Iteratively mark all phis reachable from live phis.
|
||||
while (!worklist.empty()) {
|
||||
if (mir->shouldCancel("Eliminate Phis (worklist)"))
|
||||
return false;
|
||||
|
||||
MPhi *phi = worklist.popCopy();
|
||||
JS_ASSERT(phi->isUnused());
|
||||
phi->setNotInWorklist();
|
||||
@ -200,6 +209,7 @@ ion::EliminatePhis(MIRGraph &graph)
|
||||
//
|
||||
class TypeAnalyzer
|
||||
{
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph;
|
||||
Vector<MPhi *, 0, SystemAllocPolicy> phiWorklist_;
|
||||
|
||||
@ -226,8 +236,8 @@ class TypeAnalyzer
|
||||
bool insertConversions();
|
||||
|
||||
public:
|
||||
TypeAnalyzer(MIRGraph &graph)
|
||||
: graph(graph)
|
||||
TypeAnalyzer(MIRGenerator *mir, MIRGraph &graph)
|
||||
: mir(mir), graph(graph)
|
||||
{ }
|
||||
|
||||
bool analyze();
|
||||
@ -315,6 +325,9 @@ bool
|
||||
TypeAnalyzer::specializePhis()
|
||||
{
|
||||
for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
|
||||
if (mir->shouldCancel("Specialize Phis (main loop)"))
|
||||
return false;
|
||||
|
||||
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
|
||||
MIRType type = GuessPhiType(*phi);
|
||||
phi->specialize(type);
|
||||
@ -331,6 +344,9 @@ TypeAnalyzer::specializePhis()
|
||||
}
|
||||
|
||||
while (!phiWorklist_.empty()) {
|
||||
if (mir->shouldCancel("Specialize Phis (worklist)"))
|
||||
return false;
|
||||
|
||||
MPhi *phi = popPhi();
|
||||
if (!propagateSpecialization(phi))
|
||||
return false;
|
||||
@ -422,6 +438,9 @@ TypeAnalyzer::insertConversions()
|
||||
// seen before uses. This ensures that output adjustment (which may rewrite
|
||||
// inputs of uses) does not conflict with input adjustment.
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
if (mir->shouldCancel("Insert Conversions"))
|
||||
return false;
|
||||
|
||||
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd();) {
|
||||
if (phi->type() <= MIRType_Null || phi->type() == MIRType_Magic) {
|
||||
replaceRedundantPhi(*phi);
|
||||
@ -450,9 +469,9 @@ TypeAnalyzer::analyze()
|
||||
}
|
||||
|
||||
bool
|
||||
ion::ApplyTypeInformation(MIRGraph &graph)
|
||||
ion::ApplyTypeInformation(MIRGenerator *mir, MIRGraph &graph)
|
||||
{
|
||||
TypeAnalyzer analyzer(graph);
|
||||
TypeAnalyzer analyzer(mir, graph);
|
||||
|
||||
if (!analyzer.analyze())
|
||||
return false;
|
||||
|
@ -22,13 +22,13 @@ bool
|
||||
SplitCriticalEdges(MIRGraph &graph);
|
||||
|
||||
bool
|
||||
EliminatePhis(MIRGraph &graph);
|
||||
EliminatePhis(MIRGenerator *mir, MIRGraph &graph);
|
||||
|
||||
bool
|
||||
EliminateDeadCode(MIRGraph &graph);
|
||||
EliminateDeadCode(MIRGenerator *mir, MIRGraph &graph);
|
||||
|
||||
bool
|
||||
ApplyTypeInformation(MIRGraph &graph);
|
||||
ApplyTypeInformation(MIRGenerator *mir, MIRGraph &graph);
|
||||
|
||||
bool
|
||||
RenumberBlocks(MIRGraph &graph);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Ion.h"
|
||||
#include "IonBuilder.h"
|
||||
#include "IonSpewer.h"
|
||||
#include "LICM.h"
|
||||
#include "MIR.h"
|
||||
@ -74,8 +75,8 @@ ion::ExtractLinearInequality(MTest *test, BranchDirection direction,
|
||||
return true;
|
||||
}
|
||||
|
||||
LICM::LICM(MIRGraph &graph)
|
||||
: graph(graph)
|
||||
LICM::LICM(MIRGenerator *mir, MIRGraph &graph)
|
||||
: mir(mir), graph(graph)
|
||||
{
|
||||
}
|
||||
|
||||
@ -93,7 +94,7 @@ LICM::analyze()
|
||||
continue;
|
||||
|
||||
// Attempt to optimize loop.
|
||||
Loop loop(header->backedge(), header, graph);
|
||||
Loop loop(mir, header->backedge(), header, graph);
|
||||
|
||||
Loop::LoopReturn lr = loop.init();
|
||||
if (lr == Loop::LoopReturn_Error)
|
||||
@ -108,8 +109,9 @@ LICM::analyze()
|
||||
return true;
|
||||
}
|
||||
|
||||
Loop::Loop(MBasicBlock *footer, MBasicBlock *header, MIRGraph &graph)
|
||||
: graph(graph),
|
||||
Loop::Loop(MIRGenerator *mir, MBasicBlock *footer, MBasicBlock *header, MIRGraph &graph)
|
||||
: mir(mir),
|
||||
graph(graph),
|
||||
footer_(footer),
|
||||
header_(header)
|
||||
{
|
||||
@ -181,6 +183,9 @@ Loop::optimize()
|
||||
IonSpew(IonSpew_LICM, "These instructions are in the loop: ");
|
||||
|
||||
while (!worklist_.empty()) {
|
||||
if (mir->shouldCancel("LICM (worklist)"))
|
||||
return false;
|
||||
|
||||
MInstruction *ins = popFromWorklist();
|
||||
|
||||
IonSpewHeader(IonSpew_LICM);
|
||||
|
@ -25,10 +25,11 @@ typedef Vector<MInstruction*, 1, IonAllocPolicy> InstructionQueue;
|
||||
|
||||
class LICM
|
||||
{
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph;
|
||||
|
||||
public:
|
||||
LICM(MIRGraph &graph);
|
||||
LICM(MIRGenerator *mir, MIRGraph &graph);
|
||||
bool analyze();
|
||||
};
|
||||
|
||||
@ -40,6 +41,7 @@ ExtractLinearInequality(MTest *test, BranchDirection direction,
|
||||
|
||||
class Loop
|
||||
{
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph;
|
||||
|
||||
public:
|
||||
@ -52,7 +54,7 @@ class Loop
|
||||
|
||||
public:
|
||||
// A loop is constructed on a backedge found in the control flow graph.
|
||||
Loop(MBasicBlock *header, MBasicBlock *footer, MIRGraph &graph);
|
||||
Loop(MIRGenerator *mir, MBasicBlock *header, MBasicBlock *footer, MIRGraph &graph);
|
||||
|
||||
// Initializes the loop, finds all blocks and instructions contained in the loop.
|
||||
LoopReturn init();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <limits.h>
|
||||
#include "BitSet.h"
|
||||
#include "LinearScan.h"
|
||||
#include "IonBuilder.h"
|
||||
#include "IonSpewer.h"
|
||||
#include "LIR-inl.h"
|
||||
|
||||
@ -389,6 +390,9 @@ LinearScanAllocator::createDataStructures()
|
||||
|
||||
// Build virtual register objects
|
||||
for (size_t i = 0; i < graph.numBlocks(); i++) {
|
||||
if (mir->shouldCancel("LSRA create data structures (main loop)"))
|
||||
return false;
|
||||
|
||||
LBlock *block = graph.getBlock(i);
|
||||
for (LInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
|
||||
for (size_t j = 0; j < ins->numDefs(); j++) {
|
||||
@ -481,6 +485,9 @@ LinearScanAllocator::buildLivenessInfo()
|
||||
return false;
|
||||
|
||||
for (size_t i = graph.numBlocks(); i > 0; i--) {
|
||||
if (mir->shouldCancel("LSRA Build Liveness Info (main loop)"))
|
||||
return false;
|
||||
|
||||
LBlock *block = graph.getBlock(i - 1);
|
||||
MBasicBlock *mblock = block->mir();
|
||||
|
||||
@ -793,6 +800,9 @@ LinearScanAllocator::allocateRegisters()
|
||||
JS_ASSERT(current->getAllocation()->isUse());
|
||||
JS_ASSERT(current->numRanges() > 0);
|
||||
|
||||
if (mir->shouldCancel("LSRA Allocate Registers (main loop)"))
|
||||
return false;
|
||||
|
||||
CodePosition position = current->start();
|
||||
Requirement *req = current->requirement();
|
||||
Requirement *hint = current->hint();
|
||||
@ -924,6 +934,9 @@ bool
|
||||
LinearScanAllocator::resolveControlFlow()
|
||||
{
|
||||
for (size_t i = 0; i < graph.numBlocks(); i++) {
|
||||
if (mir->shouldCancel("LSRA Resolve Control Flow (main loop)"))
|
||||
return false;
|
||||
|
||||
LBlock *successor = graph.getBlock(i);
|
||||
MBasicBlock *mSuccessor = successor->mir();
|
||||
if (mSuccessor->numPredecessors() < 1)
|
||||
@ -1007,6 +1020,9 @@ LinearScanAllocator::reifyAllocations()
|
||||
// Iterate over each interval, ensuring that definitions are visited before uses.
|
||||
for (size_t j = 1; j < graph.numVirtualRegisters(); j++) {
|
||||
VirtualRegister *reg = &vregs[j];
|
||||
if (mir->shouldCancel("LSRA Reification (main loop)"))
|
||||
return false;
|
||||
|
||||
for (size_t k = 0; k < reg->numIntervals(); k++) {
|
||||
LiveInterval *interval = reg->getInterval(k);
|
||||
JS_ASSERT(reg == interval->reg());
|
||||
@ -1972,31 +1988,49 @@ LinearScanAllocator::go()
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Creation of initial data structures completed");
|
||||
|
||||
if (mir->shouldCancel("LSRA Create Data Structures"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Beginning liveness analysis");
|
||||
if (!buildLivenessInfo())
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Liveness analysis complete");
|
||||
|
||||
if (mir->shouldCancel("LSRA Liveness"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Beginning preliminary register allocation");
|
||||
if (!allocateRegisters())
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Preliminary register allocation complete");
|
||||
|
||||
if (mir->shouldCancel("LSRA Preliminary Regalloc"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Beginning control flow resolution");
|
||||
if (!resolveControlFlow())
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Control flow resolution complete");
|
||||
|
||||
if (mir->shouldCancel("LSRA Control Flow"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Beginning register allocation reification");
|
||||
if (!reifyAllocations())
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Register allocation reification complete");
|
||||
|
||||
if (mir->shouldCancel("LSRA Reification"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Beginning safepoint population.");
|
||||
if (!populateSafepoints())
|
||||
return false;
|
||||
IonSpew(IonSpew_RegAlloc, "Safepoint population complete.");
|
||||
|
||||
if (mir->shouldCancel("LSRA Safepoints"))
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_RegAlloc, "Register allocation complete");
|
||||
|
||||
return true;
|
||||
|
@ -591,6 +591,7 @@ class LinearScanAllocator
|
||||
};
|
||||
|
||||
// Context
|
||||
MIRGenerator *mir;
|
||||
LIRGenerator *lir;
|
||||
LIRGraph &graph;
|
||||
|
||||
@ -685,8 +686,9 @@ class LinearScanAllocator
|
||||
#endif
|
||||
|
||||
public:
|
||||
LinearScanAllocator(LIRGenerator *lir, LIRGraph &graph)
|
||||
: lir(lir),
|
||||
LinearScanAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph)
|
||||
: mir(mir),
|
||||
lir(lir),
|
||||
graph(graph),
|
||||
allRegisters_(RegisterSet::All())
|
||||
{
|
||||
|
@ -2123,6 +2123,9 @@ LIRGenerator::generate()
|
||||
{
|
||||
// Create all blocks and prep all phis beforehand.
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
if (gen->shouldCancel("Lowering (preparation loop)"))
|
||||
return false;
|
||||
|
||||
current = LBlock::New(*block);
|
||||
if (!current)
|
||||
return false;
|
||||
@ -2143,6 +2146,9 @@ LIRGenerator::generate()
|
||||
}
|
||||
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
if (gen->shouldCancel("Lowering (main loop)"))
|
||||
return false;
|
||||
|
||||
if (!visitBlock(*block))
|
||||
return false;
|
||||
}
|
||||
|
@ -64,6 +64,14 @@ class MIRGenerator
|
||||
return compartment->rt->spsProfiler.enabled();
|
||||
}
|
||||
|
||||
// Whether the main thread is trying to cancel this build.
|
||||
bool shouldCancel(const char *why) {
|
||||
return cancelBuild_;
|
||||
}
|
||||
void cancel() {
|
||||
cancelBuild_ = 1;
|
||||
}
|
||||
|
||||
public:
|
||||
JSCompartment *compartment;
|
||||
|
||||
@ -74,6 +82,7 @@ class MIRGenerator
|
||||
uint32 nslots_;
|
||||
MIRGraph *graph_;
|
||||
bool error_;
|
||||
size_t cancelBuild_;
|
||||
};
|
||||
|
||||
} // namespace ion
|
||||
|
@ -22,7 +22,8 @@ MIRGenerator::MIRGenerator(JSCompartment *compartment,
|
||||
info_(info),
|
||||
temp_(temp),
|
||||
graph_(graph),
|
||||
error_(false)
|
||||
error_(false),
|
||||
cancelBuild_(0)
|
||||
{ }
|
||||
|
||||
bool
|
||||
|
@ -6,6 +6,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Ion.h"
|
||||
#include "IonBuilder.h"
|
||||
#include "IonSpewer.h"
|
||||
#include "CompileInfo.h"
|
||||
#include "ValueNumbering.h"
|
||||
@ -13,8 +14,9 @@
|
||||
using namespace js;
|
||||
using namespace js::ion;
|
||||
|
||||
ValueNumberer::ValueNumberer(MIRGraph &graph, bool optimistic)
|
||||
: graph_(graph),
|
||||
ValueNumberer::ValueNumberer(MIRGenerator *mir, MIRGraph &graph, bool optimistic)
|
||||
: mir(mir),
|
||||
graph_(graph),
|
||||
pessimisticPass_(!optimistic),
|
||||
count_(0)
|
||||
{ }
|
||||
@ -145,6 +147,8 @@ ValueNumberer::computeValueNumbers()
|
||||
return false;
|
||||
// Stick a VN object onto every mdefinition
|
||||
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
|
||||
if (mir->shouldCancel("Value Numbering (preparation loop"))
|
||||
return false;
|
||||
for (MDefinitionIterator iter(*block); iter; iter++)
|
||||
iter->setValueNumberData(new ValueNumberData);
|
||||
MControlInstruction *jump = block->lastIns();
|
||||
@ -189,6 +193,8 @@ ValueNumberer::computeValueNumbers()
|
||||
}
|
||||
#endif
|
||||
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
|
||||
if (mir->shouldCancel("Value Numbering (main loop)"))
|
||||
return false;
|
||||
for (MDefinitionIterator iter(*block); iter; ) {
|
||||
|
||||
if (!isMarked(*iter)) {
|
||||
@ -325,6 +331,8 @@ ValueNumberer::eliminateRedundancies()
|
||||
|
||||
// Starting from each self-dominating block, traverse the CFG in pre-order.
|
||||
while (!worklist.empty()) {
|
||||
if (mir->shouldCancel("Value Numbering (eliminate loop)"))
|
||||
return false;
|
||||
MBasicBlock *block = worklist.popCopy();
|
||||
|
||||
IonSpew(IonSpew_GVN, "Looking at block %d", block->id());
|
||||
|
@ -77,13 +77,14 @@ class ValueNumberer
|
||||
void breakClass(MDefinition*);
|
||||
|
||||
protected:
|
||||
MIRGenerator *mir;
|
||||
MIRGraph &graph_;
|
||||
ValueMap values;
|
||||
bool pessimisticPass_;
|
||||
size_t count_;
|
||||
|
||||
public:
|
||||
ValueNumberer(MIRGraph &graph, bool optimistic);
|
||||
ValueNumberer(MIRGenerator *mir, MIRGraph &graph, bool optimistic);
|
||||
bool analyze();
|
||||
};
|
||||
|
||||
|
@ -98,8 +98,12 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script)
|
||||
/* Wait for in progress entries to finish up. */
|
||||
for (size_t i = 0; i < state.numThreads; i++) {
|
||||
const WorkerThread &helper = state.threads[i];
|
||||
while (helper.ionScript && CompiledScriptMatches(compartment, script, helper.ionScript))
|
||||
while (helper.ionBuilder &&
|
||||
CompiledScriptMatches(compartment, script, helper.ionBuilder->script()))
|
||||
{
|
||||
helper.ionBuilder->cancel();
|
||||
state.wait(WorkerThreadState::MAIN);
|
||||
}
|
||||
}
|
||||
|
||||
ion::OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations();
|
||||
@ -276,7 +280,7 @@ WorkerThread::threadLoop()
|
||||
state.lock();
|
||||
|
||||
while (true) {
|
||||
JS_ASSERT(!ionScript);
|
||||
JS_ASSERT(!ionBuilder);
|
||||
|
||||
while (state.ionWorklist.empty()) {
|
||||
if (terminate) {
|
||||
@ -286,22 +290,21 @@ WorkerThread::threadLoop()
|
||||
state.wait(WorkerThreadState::WORKER);
|
||||
}
|
||||
|
||||
ion::IonBuilder *builder = state.ionWorklist.popCopy();
|
||||
ionScript = builder->script();
|
||||
ionBuilder = state.ionWorklist.popCopy();
|
||||
|
||||
JS_ASSERT(ionScript->ion == ION_COMPILING_SCRIPT);
|
||||
JS_ASSERT(ionBuilder->script()->ion == ION_COMPILING_SCRIPT);
|
||||
|
||||
state.unlock();
|
||||
|
||||
{
|
||||
ion::IonContext ictx(NULL, ionScript->compartment(), &builder->temp());
|
||||
builder->backgroundCompiledLir = ion::CompileBackEnd(builder);
|
||||
ion::IonContext ictx(NULL, ionBuilder->script()->compartment(), &ionBuilder->temp());
|
||||
ionBuilder->backgroundCompiledLir = ion::CompileBackEnd(ionBuilder);
|
||||
}
|
||||
|
||||
state.lock();
|
||||
|
||||
ionScript = NULL;
|
||||
FinishOffThreadIonCompile(builder);
|
||||
FinishOffThreadIonCompile(ionBuilder);
|
||||
ionBuilder = NULL;
|
||||
|
||||
/*
|
||||
* Notify the main thread in case it is waiting for the compilation to
|
||||
|
@ -87,8 +87,8 @@ struct WorkerThread
|
||||
/* Indicate to an idle thread that it should finish executing. */
|
||||
bool terminate;
|
||||
|
||||
/* Any script currently being compiled for Ion on this thread. */
|
||||
JSScript *ionScript;
|
||||
/* Any builder currently being compiled by Ion on this thread. */
|
||||
ion::IonBuilder *ionBuilder;
|
||||
|
||||
void destroy();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user