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; }
bool MBasicBlock::setBackedgeWasm(MBasicBlock* pred) { // Predecessors must be finished, and at the correct stack depth. MOZ_ASSERT(hasLastIns()); MOZ_ASSERT(pred->hasLastIns()); MOZ_ASSERT(stackDepth() == pred->stackDepth()); // We must be a pending loop header MOZ_ASSERT(kind_ == PENDING_LOOP_HEADER); // Add exit definitions to each corresponding phi at the entry. // Note: Phis are inserted in the same order as the slots. (see // MBasicBlock::New) size_t slot = 0; for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++, slot++) { MPhi* entryDef = *phi; MDefinition* exitDef = pred->getSlot(slot); // Assert that we already placed phis for each slot. MOZ_ASSERT(entryDef->block() == this); // Assert that the phi already has the correct type. MOZ_ASSERT(entryDef->type() == exitDef->type()); MOZ_ASSERT(entryDef->type() != MIRType::Value); if (entryDef == exitDef) { // If the exit def is the same as the entry def, make a redundant // phi. Since loop headers have exactly two incoming edges, we // know that that's just the first input. // // Note that we eliminate later rather than now, to avoid any // weirdness around pending continue edges which might still hold // onto phis. exitDef = entryDef->getOperand(0); } // Phis always have room for 2 operands, so this can't fail. MOZ_ASSERT(phi->numOperands() == 1); entryDef->addInlineInput(exitDef); MOZ_ASSERT(slot < pred->stackDepth()); setSlot(slot, entryDef); } // We are now a loop header proper kind_ = LOOP_HEADER; return predecessors_.append(pred); }
bool MBasicBlock::inherit(TempAllocator& alloc, size_t stackDepth, MBasicBlock* maybePred, uint32_t popped, unsigned stackPhiCount) { MOZ_ASSERT_IF(maybePred, maybePred->stackDepth() == stackDepth); MOZ_ASSERT(stackDepth >= popped); stackDepth -= popped; stackPosition_ = stackDepth; if (maybePred && kind_ != PENDING_LOOP_HEADER) copySlots(maybePred); MOZ_ASSERT(info_.nslots() >= stackPosition_); MOZ_ASSERT(!entryResumePoint_); // Propagate the caller resume point from the inherited block. callerResumePoint_ = maybePred ? maybePred->callerResumePoint() : nullptr; // Create a resume point using our initial stack state. entryResumePoint_ = new(alloc) MResumePoint(this, pc(), MResumePoint::ResumeAt); if (!entryResumePoint_->init(alloc)) return false; if (maybePred) { if (!predecessors_.append(maybePred)) return false; if (kind_ == PENDING_LOOP_HEADER) { size_t i = 0; for (i = 0; i < info().firstStackSlot(); i++) { MPhi* phi = MPhi::New(alloc.fallible()); if (!phi) return false; phi->addInlineInput(maybePred->getSlot(i)); addPhi(phi); setSlot(i, phi); entryResumePoint()->initOperand(i, phi); } MOZ_ASSERT(stackPhiCount <= stackDepth); MOZ_ASSERT(info().firstStackSlot() <= stackDepth - stackPhiCount); // Avoid creating new phis for stack values that aren't part of the // loop. Note that for loop headers that can OSR, all values on the // stack are part of the loop. for (; i < stackDepth - stackPhiCount; i++) { MDefinition* val = maybePred->getSlot(i); setSlot(i, val); entryResumePoint()->initOperand(i, val); } for (; i < stackDepth; i++) { MPhi* phi = MPhi::New(alloc.fallible()); if (!phi) return false; phi->addInlineInput(maybePred->getSlot(i)); addPhi(phi); setSlot(i, phi); entryResumePoint()->initOperand(i, phi); } } else { for (size_t i = 0; i < stackDepth; i++) entryResumePoint()->initOperand(i, getSlot(i)); } } else { /* * Don't leave the operands uninitialized for the caller, as it may not * initialize them later on. */ for (size_t i = 0; i < stackDepth; i++) entryResumePoint()->clearOperand(i); } return true; }