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; }
bool TypeBarrierPolicy::adjustInputs(TempAllocator &alloc, MInstruction *def) { 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. JS_ASSERT(inputType != MIRType_Value); ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0))); return true; } // Input is a value. Unbox the input to the requested type. if (inputType == MIRType_Value) { JS_ASSERT(outputType != MIRType_Value); // We can't unbox a value to null/undefined/lazyargs. So keep output // also a value. if (IsNullOrUndefined(outputType) || outputType == MIRType_MagicOptimizedArguments) { JS_ASSERT(!ins->hasDefUses()); ins->setResultType(MIRType_Value); return true; } MUnbox *unbox = MUnbox::New(alloc, ins->getOperand(0), outputType, MUnbox::TypeBarrier); ins->block()->insertBefore(ins, unbox); ins->replaceOperand(0, unbox); return true; } // In the remaining cases we will alway bail. OutputType doesn't matter. // Take inputType so we can use redefine during lowering. JS_ASSERT(ins->alwaysBails()); ins->setResultType(inputType); return true; }