bool TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def) const { MTypeBarrier* ins = def->toTypeBarrier(); MIRType inputType = ins->getOperand(0)->type(); MIRType outputType = ins->type(); // Input and output type are already in accordance. if (inputType == outputType) { return true; } // Output is a value, currently box the input. if (outputType == MIRType::Value) { // XXX: Possible optimization: decrease resultTypeSet to only include // the inputType. This will remove the need for boxing. MOZ_ASSERT(inputType != MIRType::Value); ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0))); return true; } // Box input if needed. if (inputType != MIRType::Value) { MOZ_ASSERT(ins->alwaysBails()); ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0))); } // We can't unbox a value to null/undefined/lazyargs. So keep output // also a value. // Note: Using setResultType shouldn't be done in TypePolicies, // Here it is fine, since the type barrier has no uses. if (IsNullOrUndefined(outputType) || outputType == MIRType::MagicOptimizedArguments) { MOZ_ASSERT(!ins->hasDefUses()); ins->setResultType(MIRType::Value); return true; } // Unbox / propagate the right type. MUnbox::Mode mode = MUnbox::TypeBarrier; MInstruction* replace = MUnbox::New(alloc, ins->getOperand(0), ins->type(), mode); if (!ins->isMovable()) { replace->setNotMovable(); } ins->block()->insertBefore(ins, replace); ins->replaceOperand(0, replace); if (!replace->typePolicy()->adjustInputs(alloc, replace)) { return false; } // The TypeBarrier is equivalent to removing branches with unexpected // types. The unexpected types would have changed Range Analysis // predictions. As such, we need to prevent destructive optimizations. ins->block()->flagOperandsOfPrunedBranches(replace); return true; }