bool MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) { if (pred) { stackPosition_ = pred->stackPosition_; JS_ASSERT(stackPosition_ >= popped); stackPosition_ -= popped; if (kind_ != PENDING_LOOP_HEADER) copySlots(pred); } else if (pc()) { uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth; stackPosition_ = info().firstStackSlot() + stackDepth; JS_ASSERT(stackPosition_ >= popped); stackPosition_ -= popped; } else { stackPosition_ = info().firstStackSlot(); } JS_ASSERT(info_.nslots() >= stackPosition_); JS_ASSERT(!entryResumePoint_); if (pc()) { // Propagate the caller resume point from the inherited block. MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL; // Create a resume point using our initial stack state. entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt); if (!entryResumePoint_->init()) return false; } if (pred) { if (!predecessors_.append(pred)) return false; if (kind_ == PENDING_LOOP_HEADER) { for (size_t i = 0; i < stackDepth(); i++) { MPhi *phi = MPhi::New(i); if (!phi->initLength(1)) return false; phi->setOperand(0, pred->getSlot(i)); addPhi(phi); setSlot(i, phi); if (entryResumePoint()) entryResumePoint()->setOperand(i, phi); } } else if (entryResumePoint()) { for (size_t i = 0; i < stackDepth(); i++) entryResumePoint()->setOperand(i, getSlot(i)); } } return true; }
bool MBasicBlock::addPredecessorPopN(MBasicBlock *pred, uint32_t popped) { JS_ASSERT(pred); JS_ASSERT(predecessors_.length() > 0); // Predecessors must be finished, and at the correct stack depth. JS_ASSERT(pred->lastIns_); JS_ASSERT(pred->stackPosition_ == stackPosition_ + popped); for (uint32_t i = 0; i < stackPosition_; i++) { MDefinition *mine = getSlot(i); MDefinition *other = pred->getSlot(i); if (mine != other) { // If the current instruction is a phi, and it was created in this // basic block, then we have already placed this phi and should // instead append to its operands. if (mine->isPhi() && mine->block() == this) { JS_ASSERT(predecessors_.length()); if (!mine->toPhi()->addInputSlow(other)) return false; } else { // Otherwise, create a new phi node. MPhi *phi = MPhi::New(i); addPhi(phi); // Prime the phi for each predecessor, so input(x) comes from // predecessor(x). if (!phi->initLength(predecessors_.length() + 1)) return false; for (size_t j = 0; j < predecessors_.length(); j++) { JS_ASSERT(predecessors_[j]->getSlot(i) == mine); phi->setOperand(j, mine); } phi->setOperand(predecessors_.length(), other); setSlot(i, phi); if (entryResumePoint()) entryResumePoint()->replaceOperand(i, phi); } } } return predecessors_.append(pred); }