MBasicBlock * MBasicBlock::NewAsmJS(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, Kind kind) { MBasicBlock *block = new MBasicBlock(graph, info, /* entryPC = */ NULL, kind); if (!block->init()) return NULL; if (pred) { block->stackPosition_ = pred->stackPosition_; if (block->kind_ == PENDING_LOOP_HEADER) { for (size_t i = 0; i < block->stackPosition_; i++) { MDefinition *predSlot = pred->getSlot(i); JS_ASSERT(predSlot->type() != MIRType_Value); MPhi *phi = MPhi::New(i, predSlot->type()); JS_ALWAYS_TRUE(phi->reserveLength(2)); phi->addInput(predSlot); block->addPhi(phi); block->setSlot(i, phi); } } else { block->copySlots(pred); } if (!block->predecessors_.append(pred)) return NULL; } return block; }
MBasicBlock* MBasicBlock::New(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred, Kind kind) { BytecodeSite* site = new(graph.alloc()) BytecodeSite(); MBasicBlock* block = new(graph.alloc()) MBasicBlock(graph, info, site, kind); if (!block->init()) return nullptr; if (pred) { block->stackPosition_ = pred->stackPosition_; if (block->kind_ == PENDING_LOOP_HEADER) { size_t nphis = block->stackPosition_; size_t nfree = graph.phiFreeListLength(); TempAllocator& alloc = graph.alloc(); MPhi* phis = nullptr; if (nphis > nfree) { phis = alloc.allocateArray<MPhi>(nphis - nfree); if (!phis) return nullptr; } // Note: Phis are inserted in the same order as the slots. for (size_t i = 0; i < nphis; i++) { MDefinition* predSlot = pred->getSlot(i); MOZ_ASSERT(predSlot->type() != MIRType::Value); MPhi* phi; if (i < nfree) phi = graph.takePhiFromFreeList(); else phi = phis + (i - nfree); new(phi) MPhi(alloc, predSlot->type()); phi->addInlineInput(predSlot); // Add append Phis in the block. block->addPhi(phi); block->setSlot(i, phi); } } else { block->copySlots(pred); } if (!block->predecessors_.append(pred)) return nullptr; } return block; }
MBasicBlock * MBasicBlock::NewPopN(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popped) { MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind); if (!block->init()) return NULL; if (!block->inherit(pred, popped)) return NULL; return block; }
MBasicBlock * MBasicBlock::NewPopN(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, const BytecodeSite &site, Kind kind, uint32_t popped) { MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, site, kind); if (!block->init()) return nullptr; if (!block->inherit(graph.alloc(), nullptr, pred, popped)) return nullptr; return block; }
MBasicBlock * MBasicBlock::New(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind) { JS_ASSERT(entryPc != NULL); MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind); if (!block->init()) return NULL; if (!block->inherit(pred, 0)) return NULL; return block; }
MBasicBlock * MBasicBlock::New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, MBasicBlock *pred, const BytecodeSite &site, Kind kind) { JS_ASSERT(site.pc() != nullptr); MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, site, kind); if (!block->init()) return nullptr; if (!block->inherit(graph.alloc(), analysis, pred, 0)) return nullptr; return block; }
MBasicBlock* MBasicBlock::New(MIRGraph& graph, size_t stackDepth, const CompileInfo& info, MBasicBlock* maybePred, BytecodeSite* site, Kind kind) { MOZ_ASSERT(site->pc() != nullptr); MBasicBlock* block = new(graph.alloc()) MBasicBlock(graph, info, site, kind); if (!block->init()) return nullptr; if (!block->inherit(graph.alloc(), stackDepth, maybePred, 0)) return nullptr; return block; }
MBasicBlock * MBasicBlock::New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind) { JS_ASSERT(entryPc != nullptr); MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind); if (!block->init()) return nullptr; if (!block->inherit(analysis, pred, 0)) return nullptr; return block; }
MBasicBlock * MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, const BytecodeSite &site, unsigned stackPhiCount) { JS_ASSERT(site.pc() != nullptr); MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, site, PENDING_LOOP_HEADER); if (!block->init()) return nullptr; if (!block->inherit(graph.alloc(), nullptr, pred, 0, stackPhiCount)) return nullptr; return block; }
MBasicBlock * MBasicBlock::NewWithResumePoint(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, MResumePoint *resumePoint) { MBasicBlock *block = new MBasicBlock(graph, info, entryPc, NORMAL); resumePoint->block_ = block; block->entryResumePoint_ = resumePoint; if (!block->init()) return NULL; if (!block->inheritResumePoint(pred)) return NULL; return block; }
MBasicBlock * MBasicBlock::NewWithResumePoint(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, const BytecodeSite &site, MResumePoint *resumePoint) { MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, site, NORMAL); resumePoint->block_ = block; block->entryResumePoint_ = resumePoint; if (!block->init()) return nullptr; if (!block->inheritResumePoint(pred)) return nullptr; return block; }
MBasicBlock * MBasicBlock::NewAbortPar(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, MResumePoint *resumePoint) { MBasicBlock *block = new MBasicBlock(graph, info, entryPc, NORMAL); resumePoint->block_ = block; block->entryResumePoint_ = resumePoint; if (!block->init()) return NULL; if (!block->addPredecessorWithoutPhis(pred)) return NULL; block->end(new MAbortPar()); return block; }
MBasicBlock * MBasicBlock::NewAbortPar(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, const BytecodeSite &site, MResumePoint *resumePoint) { MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, site, NORMAL); resumePoint->block_ = block; block->entryResumePoint_ = resumePoint; if (!block->init()) return nullptr; if (!block->addPredecessorWithoutPhis(pred)) return nullptr; block->end(MAbortPar::New(graph.alloc())); return block; }
MBasicBlock * MBasicBlock::NewAsmJS(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, Kind kind) { MBasicBlock *block = new(graph.alloc()) MBasicBlock(graph, info, BytecodeSite(), kind); if (!block->init()) return nullptr; if (pred) { block->stackPosition_ = pred->stackPosition_; if (block->kind_ == PENDING_LOOP_HEADER) { size_t nphis = block->stackPosition_; TempAllocator &alloc = graph.alloc(); MPhi *phis = (MPhi*)alloc.allocateArray<sizeof(MPhi)>(nphis); if (!phis) return nullptr; // Note: Phis are inserted in the same order as the slots. for (size_t i = 0; i < nphis; i++) { MDefinition *predSlot = pred->getSlot(i); JS_ASSERT(predSlot->type() != MIRType_Value); MPhi *phi = new(phis + i) MPhi(alloc, predSlot->type()); JS_ALWAYS_TRUE(phi->reserveLength(2)); phi->addInput(predSlot); // Add append Phis in the block. block->addPhi(phi); block->setSlot(i, phi); } } else { block->copySlots(pred); } if (!block->predecessors_.append(pred)) return nullptr; } return block; }
MBasicBlock* MBasicBlock::NewWithResumePoint(MIRGraph& graph, CompileInfo& info, MBasicBlock* pred, BytecodeSite* site, MResumePoint* resumePoint) { MBasicBlock* block = new(graph.alloc()) MBasicBlock(graph, info, site, NORMAL); MOZ_ASSERT(!resumePoint->instruction()); resumePoint->block()->discardResumePoint(resumePoint, RefType_None); resumePoint->block_ = block; block->addResumePoint(resumePoint); block->entryResumePoint_ = resumePoint; if (!block->init()) return nullptr; if (!block->inheritResumePoint(pred)) return nullptr; return block; }
MBasicBlock* MBasicBlock::NewSplitEdge(MIRGraph& graph, MBasicBlock* pred, size_t predEdgeIdx, MBasicBlock* succ) { MBasicBlock* split = nullptr; if (!succ->pc()) { // The predecessor does not have a PC, this is a Wasm compilation. split = MBasicBlock::New(graph, succ->info(), pred, SPLIT_EDGE); if (!split) return nullptr; } else { // The predecessor has a PC, this is an IonBuilder compilation. MResumePoint* succEntry = succ->entryResumePoint(); BytecodeSite* site = new(graph.alloc()) BytecodeSite(succ->trackedTree(), succEntry->pc()); split = new(graph.alloc()) MBasicBlock(graph, succ->info(), site, SPLIT_EDGE); if (!split->init()) return nullptr; // A split edge is used to simplify the graph to avoid having a // predecessor with multiple successors as well as a successor with // multiple predecessors. As instructions can be moved in this // split-edge block, we need to give this block a resume point. To do // so, we copy the entry resume points of the successor and filter the // phis to keep inputs from the current edge. // Propagate the caller resume point from the inherited block. split->callerResumePoint_ = succ->callerResumePoint(); // Split-edge are created after the interpreter stack emulation. Thus, // there is no need for creating slots. split->stackPosition_ = succEntry->stackDepth(); // Create a resume point using our initial stack position. MResumePoint* splitEntry = new(graph.alloc()) MResumePoint(split, succEntry->pc(), MResumePoint::ResumeAt); if (!splitEntry->init(graph.alloc())) return nullptr; split->entryResumePoint_ = splitEntry; // The target entry resume point might have phi operands, keep the // operands of the phi coming from our edge. size_t succEdgeIdx = succ->indexForPredecessor(pred); for (size_t i = 0, e = splitEntry->numOperands(); i < e; i++) { MDefinition* def = succEntry->getOperand(i); // This early in the pipeline, we have no recover instructions in // any entry resume point. MOZ_ASSERT_IF(def->block() == succ, def->isPhi()); if (def->block() == succ) def = def->toPhi()->getOperand(succEdgeIdx); splitEntry->initOperand(i, def); } // This is done in the New variant for wasm, so we cannot keep this // line below, where the rest of the graph is modified. if (!split->predecessors_.append(pred)) return nullptr; } split->setLoopDepth(succ->loopDepth()); // Insert the split edge block in-between. split->end(MGoto::New(graph.alloc(), succ)); graph.insertBlockAfter(pred, split); pred->replaceSuccessor(predEdgeIdx, split); succ->replacePredecessor(pred, split); return split; }