uint32 MPrepareCall::argc() const { JS_ASSERT(useCount() == 1); MCall *call = usesBegin()->node()->toDefinition()->toCall(); return call->argc(); }
MCall * MCall::New(size_t argc, size_t bytecodeArgc, bool construct) { MCall *ins = new MCall(construct, bytecodeArgc); if (!ins->init(argc + NumNonArgumentOperands)) return NULL; return ins; }
bool CallPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) { MCall *call = ins->toCall(); MDefinition *func = call->getFunction(); if (func->type() != MIRType_Object) { MInstruction *unbox = MUnbox::New(alloc, func, MIRType_Object, MUnbox::Fallible); call->block()->insertBefore(call, unbox); call->replaceFunction(unbox); if (!unbox->typePolicy()->adjustInputs(alloc, unbox)) return false; } for (uint32_t i = 0; i < call->numStackArgs(); i++) EnsureOperandNotFloat32(alloc, call, MCall::IndexOfStackArg(i)); return true; }
bool CallPolicy::adjustInputs(MInstruction *ins) { MCall *call = ins->toCall(); MDefinition *func = call->getFunction(); if (func->type() == MIRType_Object) return true; // If the function is impossible to call, // bail out by causing a subsequent unbox to fail. if (func->type() != MIRType_Value) func = boxAt(call, func); MInstruction *unbox = MUnbox::New(func, MIRType_Object, MUnbox::Fallible); call->block()->insertBefore(call, unbox); call->replaceFunction(unbox); return true; }
bool CallPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) { MCall *call = ins->toCall(); MDefinition *func = call->getFunction(); if (func->type() != MIRType_Object) { // If the function is impossible to call, // bail out by causing a subsequent unbox to fail. if (func->type() != MIRType_Value) func = boxAt(alloc, call, func); MInstruction *unbox = MUnbox::New(alloc, func, MIRType_Object, MUnbox::Fallible); call->block()->insertBefore(call, unbox); call->replaceFunction(unbox); } for (uint32_t i = 0; i < call->numStackArgs(); i++) EnsureOperandNotFloat32(alloc, call, MCall::IndexOfStackArg(i)); return true; }
bool UnreachableCodeElimination::removeUnmarkedBlocksAndClearDominators() { // Removes blocks that are not marked from the graph. For blocks // that *are* marked, clears the mark and adjusts the id to its // new value. Also adds blocks that are immediately reachable // from an unmarked block to the frontier. size_t id = marked_; for (PostorderIterator iter(graph_.poBegin()); iter != graph_.poEnd();) { if (mir_->shouldCancel("Eliminate Unreachable Code")) return false; MBasicBlock *block = *iter; iter++; // Unconditionally clear the dominators. It's somewhat complex to // adjust the values and relatively fast to just recompute. block->clearDominatorInfo(); if (block->isMarked()) { block->setId(--id); for (MPhiIterator iter(block->phisBegin()); iter != block->phisEnd(); iter++) checkDependencyAndRemoveUsesFromUnmarkedBlocks(*iter); for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) checkDependencyAndRemoveUsesFromUnmarkedBlocks(*iter); } else { if (block->numPredecessors() > 1) { // If this block had phis, then any reachable // predecessors need to have the successorWithPhis // flag cleared. for (size_t i = 0; i < block->numPredecessors(); i++) block->getPredecessor(i)->setSuccessorWithPhis(nullptr, 0); } if (block->isLoopBackedge()) { // NB. We have to update the loop header if we // eliminate the backedge. At first I thought this // check would be insufficient, because it would be // possible to have code like this: // // while (true) { // ...; // if (1 == 1) break; // } // // in which the backedge is removed as part of // rewriting the condition, but no actual blocks are // removed. However, in all such cases, the backedge // would be a critical edge and hence the critical // edge block is being removed. block->loopHeaderOfBackedge()->clearLoopHeader(); } for (size_t i = 0, c = block->numSuccessors(); i < c; i++) { MBasicBlock *succ = block->getSuccessor(i); if (succ->isMarked()) { // succ is on the frontier of blocks to be removed: succ->removePredecessor(block); if (!redundantPhis_) { for (MPhiIterator iter(succ->phisBegin()); iter != succ->phisEnd(); iter++) { if (iter->operandIfRedundant()) { redundantPhis_ = true; break; } } } } } // When we remove a call, we can't leave the corresponding MPassArg // in the graph. Since lowering will fail. Replace it with the // argument for the exceptional case when it is kept alive in a // ResumePoint. DCE will remove the unused MPassArg instruction. for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) { if (iter->isCall()) { MCall *call = iter->toCall(); for (size_t i = 0; i < call->numStackArgs(); i++) { JS_ASSERT(call->getArg(i)->isPassArg()); JS_ASSERT(call->getArg(i)->hasOneDefUse()); MPassArg *arg = call->getArg(i)->toPassArg(); arg->replaceAllUsesWith(arg->getArgument()); } } } graph_.removeBlock(block); } } JS_ASSERT(id == 0); return true; }