Allow canceling in-progress off thread ion compilations, bug 785761. r=dvander

This commit is contained in:
Brian Hackett 2012-10-25 12:00:00 -07:00
parent d0b0ab5ea2
commit d177fc87e2
18 changed files with 209 additions and 48 deletions

View File

@ -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);

View File

@ -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();
};

View File

@ -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();
}

View File

@ -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);

View File

@ -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", &regalloc);
if (mir->shouldCancel("Allocate Registers"))
return false;
}
return lir;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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())
{

View File

@ -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;
}

View File

@ -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

View File

@ -22,7 +22,8 @@ MIRGenerator::MIRGenerator(JSCompartment *compartment,
info_(info),
temp_(temp),
graph_(graph),
error_(false)
error_(false),
cancelBuild_(0)
{ }
bool

View File

@ -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());

View File

@ -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();
};

View File

@ -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

View File

@ -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();