LCOV - code coverage report
Current view: top level - js/src/jit - TypePolicy.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 205 566 36.2 %
Date: 2017-07-14 16:53:18 Functions: 128 775 16.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "jit/TypePolicy.h"
       8             : 
       9             : #include "jit/Lowering.h"
      10             : #include "jit/MIR.h"
      11             : #include "jit/MIRGraph.h"
      12             : 
      13             : #include "jit/shared/Lowering-shared-inl.h"
      14             : 
      15             : using namespace js;
      16             : using namespace js::jit;
      17             : 
      18             : using JS::DoubleNaNValue;
      19             : 
      20             : static void
      21         309 : EnsureOperandNotFloat32(TempAllocator& alloc, MInstruction* def, unsigned op)
      22             : {
      23         309 :     MDefinition* in = def->getOperand(op);
      24         309 :     if (in->type() == MIRType::Float32) {
      25           0 :         MToDouble* replace = MToDouble::New(alloc, in);
      26           0 :         def->block()->insertBefore(def, replace);
      27           0 :         if (def->isRecoveredOnBailout())
      28           0 :             replace->setRecoveredOnBailout();
      29           0 :         def->replaceOperand(op, replace);
      30             :     }
      31         309 : }
      32             : 
      33             : MDefinition*
      34         103 : js::jit::AlwaysBoxAt(TempAllocator& alloc, MInstruction* at, MDefinition* operand)
      35             : {
      36         103 :     MDefinition* boxedOperand = operand;
      37             :     // Replace Float32 by double
      38         103 :     if (operand->type() == MIRType::Float32) {
      39           0 :         MInstruction* replace = MToDouble::New(alloc, operand);
      40           0 :         at->block()->insertBefore(at, replace);
      41           0 :         boxedOperand = replace;
      42             :     }
      43         103 :     MBox* box = MBox::New(alloc, boxedOperand);
      44         103 :     at->block()->insertBefore(at, box);
      45         103 :     return box;
      46             : }
      47             : 
      48             : static MDefinition*
      49          19 : BoxAt(TempAllocator& alloc, MInstruction* at, MDefinition* operand)
      50             : {
      51          19 :     if (operand->isUnbox())
      52           5 :         return operand->toUnbox()->input();
      53          14 :     return AlwaysBoxAt(alloc, at, operand);
      54             : }
      55             : 
      56             : bool
      57         155 : BoxInputsPolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
      58             : {
      59         310 :     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
      60         155 :         MDefinition* in = ins->getOperand(i);
      61         155 :         if (in->type() == MIRType::Value)
      62         138 :             continue;
      63          17 :         ins->replaceOperand(i, BoxAt(alloc, ins, in));
      64             :     }
      65         155 :     return true;
      66             : }
      67             : 
      68             : bool
      69          14 : ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
      70             : {
      71          14 :     MIRType specialization = ins->typePolicySpecialization();
      72          14 :     if (specialization == MIRType::None)
      73           0 :         return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
      74             : 
      75          14 :     MOZ_ASSERT(ins->type() == MIRType::Double || ins->type() == MIRType::Int32 || ins->type() == MIRType::Float32);
      76             : 
      77          42 :     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
      78          28 :         MDefinition* in = ins->getOperand(i);
      79          28 :         if (in->type() == ins->type())
      80          28 :             continue;
      81             : 
      82             :         MInstruction* replace;
      83             : 
      84           0 :         if (ins->type() == MIRType::Double)
      85           0 :             replace = MToDouble::New(alloc, in);
      86           0 :         else if (ins->type() == MIRType::Float32)
      87           0 :             replace = MToFloat32::New(alloc, in);
      88             :         else
      89           0 :             replace = MToInt32::New(alloc, in);
      90             : 
      91           0 :         ins->block()->insertBefore(ins, replace);
      92           0 :         ins->replaceOperand(i, replace);
      93             : 
      94           0 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
      95           0 :             return false;
      96             :     }
      97             : 
      98          14 :     return true;
      99             : }
     100             : 
     101             : bool
     102           0 : AllDoublePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     103             : {
     104           0 :     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
     105           0 :         MDefinition* in = ins->getOperand(i);
     106           0 :         if (in->type() == MIRType::Double)
     107           0 :             continue;
     108             : 
     109           0 :         if (!alloc.ensureBallast())
     110           0 :             return false;
     111           0 :         MInstruction* replace = MToDouble::New(alloc, in);
     112             : 
     113           0 :         ins->block()->insertBefore(ins, replace);
     114           0 :         ins->replaceOperand(i, replace);
     115             : 
     116           0 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
     117           0 :             return false;
     118             :     }
     119             : 
     120           0 :     return true;
     121             : }
     122             : 
     123             : bool
     124          58 : ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
     125             : {
     126          58 :     MOZ_ASSERT(def->isCompare());
     127          58 :     MCompare* compare = def->toCompare();
     128             : 
     129             :     // Convert Float32 operands to doubles
     130         174 :     for (size_t i = 0; i < 2; i++) {
     131         116 :         MDefinition* in = def->getOperand(i);
     132         116 :         if (in->type() == MIRType::Float32) {
     133           0 :             MInstruction* replace = MToDouble::New(alloc, in);
     134           0 :             def->block()->insertBefore(def, replace);
     135           0 :             def->replaceOperand(i, replace);
     136             :         }
     137             :     }
     138             : 
     139             :     // Box inputs to get value
     140         116 :     if (compare->compareType() == MCompare::Compare_Unknown ||
     141          58 :         compare->compareType() == MCompare::Compare_Bitwise)
     142             :     {
     143           0 :         return BoxInputsPolicy::staticAdjustInputs(alloc, def);
     144             :     }
     145             : 
     146             :     // Compare_Boolean specialization is done for "Anything === Bool"
     147             :     // If the LHS is boolean, we set the specialization to Compare_Int32.
     148             :     // This matches other comparisons of the form bool === bool and
     149             :     // generated code of Compare_Int32 is more efficient.
     150          58 :     if (compare->compareType() == MCompare::Compare_Boolean &&
     151           0 :         def->getOperand(0)->type() == MIRType::Boolean)
     152             :     {
     153           0 :        compare->setCompareType(MCompare::Compare_Int32MaybeCoerceBoth);
     154             :     }
     155             : 
     156             :     // Compare_Boolean specialization is done for "Anything === Bool"
     157             :     // As of previous line Anything can't be Boolean
     158          58 :     if (compare->compareType() == MCompare::Compare_Boolean) {
     159             :         // Unbox rhs that is definitely Boolean
     160           0 :         MDefinition* rhs = def->getOperand(1);
     161           0 :         if (rhs->type() != MIRType::Boolean) {
     162           0 :             MInstruction* unbox = MUnbox::New(alloc, rhs, MIRType::Boolean, MUnbox::Infallible);
     163           0 :             def->block()->insertBefore(def, unbox);
     164           0 :             def->replaceOperand(1, unbox);
     165           0 :             if (!unbox->typePolicy()->adjustInputs(alloc, unbox))
     166           0 :                 return false;
     167             :         }
     168             : 
     169           0 :         MOZ_ASSERT(def->getOperand(0)->type() != MIRType::Boolean);
     170           0 :         MOZ_ASSERT(def->getOperand(1)->type() == MIRType::Boolean);
     171           0 :         return true;
     172             :     }
     173             : 
     174             :     // Compare_StrictString specialization is done for "Anything === String"
     175             :     // If the LHS is string, we set the specialization to Compare_String.
     176          58 :     if (compare->compareType() == MCompare::Compare_StrictString &&
     177           0 :         def->getOperand(0)->type() == MIRType::String)
     178             :     {
     179           0 :        compare->setCompareType(MCompare::Compare_String);
     180             :     }
     181             : 
     182             :     // Compare_StrictString specialization is done for "Anything === String"
     183             :     // As of previous line Anything can't be String
     184          58 :     if (compare->compareType() == MCompare::Compare_StrictString) {
     185             :         // Unbox rhs that is definitely String
     186           0 :         MDefinition* rhs = def->getOperand(1);
     187           0 :         if (rhs->type() != MIRType::String) {
     188           0 :             MInstruction* unbox = MUnbox::New(alloc, rhs, MIRType::String, MUnbox::Infallible);
     189           0 :             def->block()->insertBefore(def, unbox);
     190           0 :             def->replaceOperand(1, unbox);
     191           0 :             if (!unbox->typePolicy()->adjustInputs(alloc, unbox))
     192           0 :                 return false;
     193             :         }
     194             : 
     195           0 :         MOZ_ASSERT(def->getOperand(0)->type() != MIRType::String);
     196           0 :         MOZ_ASSERT(def->getOperand(1)->type() == MIRType::String);
     197           0 :         return true;
     198             :     }
     199             : 
     200         115 :     if (compare->compareType() == MCompare::Compare_Undefined ||
     201          57 :         compare->compareType() == MCompare::Compare_Null)
     202             :     {
     203             :         // Nothing to do for undefined and null, lowering handles all types.
     204           5 :         return true;
     205             :     }
     206             : 
     207             :     // Convert all inputs to the right input type
     208          53 :     MIRType type = compare->inputType();
     209          53 :     MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Double || type == MIRType::Float32 ||
     210             :                type == MIRType::Object || type == MIRType::String || type == MIRType::Symbol);
     211         159 :     for (size_t i = 0; i < 2; i++) {
     212         106 :         MDefinition* in = def->getOperand(i);
     213         106 :         if (in->type() == type)
     214         105 :             continue;
     215             : 
     216             :         MInstruction* replace;
     217             : 
     218           1 :         switch (type) {
     219             :           case MIRType::Double: {
     220           0 :             MToFPInstruction::ConversionKind convert = MToFPInstruction::NumbersOnly;
     221           0 :             if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceLHS && i == 0)
     222           0 :                 convert = MToFPInstruction::NonNullNonStringPrimitives;
     223           0 :             else if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceRHS && i == 1)
     224           0 :                 convert = MToFPInstruction::NonNullNonStringPrimitives;
     225           0 :             replace = MToDouble::New(alloc, in, convert);
     226           0 :             break;
     227             :           }
     228             :           case MIRType::Float32: {
     229           0 :             MToFPInstruction::ConversionKind convert = MToFPInstruction::NumbersOnly;
     230           0 :             if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceLHS && i == 0)
     231           0 :                 convert = MToFPInstruction::NonNullNonStringPrimitives;
     232           0 :             else if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceRHS && i == 1)
     233           0 :                 convert = MToFPInstruction::NonNullNonStringPrimitives;
     234           0 :             replace = MToFloat32::New(alloc, in, convert);
     235           0 :             break;
     236             :           }
     237             :           case MIRType::Int32: {
     238           1 :             MacroAssembler::IntConversionInputKind convert = MacroAssembler::IntConversion_NumbersOnly;
     239           3 :             if (compare->compareType() == MCompare::Compare_Int32MaybeCoerceBoth ||
     240           2 :                 (compare->compareType() == MCompare::Compare_Int32MaybeCoerceLHS && i == 0) ||
     241           1 :                 (compare->compareType() == MCompare::Compare_Int32MaybeCoerceRHS && i == 1))
     242             :             {
     243           0 :                 convert = MacroAssembler::IntConversion_NumbersOrBoolsOnly;
     244             :             }
     245           1 :             replace = MToInt32::New(alloc, in, convert);
     246           1 :             break;
     247             :           }
     248             :           case MIRType::Object:
     249           0 :             replace = MUnbox::New(alloc, in, MIRType::Object, MUnbox::Infallible);
     250           0 :             break;
     251             :           case MIRType::String:
     252           0 :             replace = MUnbox::New(alloc, in, MIRType::String, MUnbox::Infallible);
     253           0 :             break;
     254             :           case MIRType::Symbol:
     255           0 :             replace = MUnbox::New(alloc, in, MIRType::Symbol, MUnbox::Infallible);
     256           0 :             break;
     257             :           default:
     258           0 :             MOZ_CRASH("Unknown compare specialization");
     259             :         }
     260             : 
     261           1 :         def->block()->insertBefore(def, replace);
     262           1 :         def->replaceOperand(i, replace);
     263             : 
     264           1 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
     265           0 :             return false;
     266             :     }
     267             : 
     268          53 :     return true;
     269             : }
     270             : 
     271             : bool
     272         154 : TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
     273             : {
     274         154 :     MTypeBarrier* ins = def->toTypeBarrier();
     275         154 :     MIRType inputType = ins->getOperand(0)->type();
     276         154 :     MIRType outputType = ins->type();
     277             : 
     278             :     // Input and output type are already in accordance.
     279         154 :     if (inputType == outputType)
     280          57 :         return true;
     281             : 
     282             :     // Output is a value, currently box the input.
     283          97 :     if (outputType == MIRType::Value) {
     284             :         // XXX: Possible optimization: decrease resultTypeSet to only include
     285             :         // the inputType. This will remove the need for boxing.
     286           0 :         MOZ_ASSERT(inputType != MIRType::Value);
     287           0 :         ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
     288           0 :         return true;
     289             :     }
     290             : 
     291             :     // Box input if needed.
     292          97 :     if (inputType != MIRType::Value) {
     293           0 :         MOZ_ASSERT(ins->alwaysBails());
     294           0 :         ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
     295             :     }
     296             : 
     297             :     // We can't unbox a value to null/undefined/lazyargs. So keep output
     298             :     // also a value.
     299             :     // Note: Using setResultType shouldn't be done in TypePolicies,
     300             :     //       Here it is fine, since the type barrier has no uses.
     301          97 :     if (IsNullOrUndefined(outputType) || outputType == MIRType::MagicOptimizedArguments) {
     302          14 :         MOZ_ASSERT(!ins->hasDefUses());
     303          14 :         ins->setResultType(MIRType::Value);
     304          14 :         return true;
     305             :     }
     306             : 
     307             :     // Unbox / propagate the right type.
     308          83 :     MUnbox::Mode mode = MUnbox::TypeBarrier;
     309          83 :     MInstruction* replace = MUnbox::New(alloc, ins->getOperand(0), ins->type(), mode);
     310          83 :     if (!ins->isMovable())
     311           0 :         replace->setNotMovable();
     312             : 
     313          83 :     ins->block()->insertBefore(ins, replace);
     314          83 :     ins->replaceOperand(0, replace);
     315          83 :     if (!replace->typePolicy()->adjustInputs(alloc, replace))
     316           0 :         return false;
     317             : 
     318             :     // The TypeBarrier is equivalent to removing branches with unexpected
     319             :     // types.  The unexpected types would have changed Range Analysis
     320             :     // predictions.  As such, we need to prevent destructive optimizations.
     321          83 :     ins->block()->flagOperandsOfPrunedBranches(replace);
     322             : 
     323          83 :     return true;
     324             : }
     325             : 
     326             : bool
     327         167 : TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     328             : {
     329         167 :     MDefinition* op = ins->getOperand(0);
     330         167 :     switch (op->type()) {
     331             :       case MIRType::Value:
     332             :       case MIRType::Null:
     333             :       case MIRType::Undefined:
     334             :       case MIRType::Boolean:
     335             :       case MIRType::Int32:
     336             :       case MIRType::Double:
     337             :       case MIRType::Float32:
     338             :       case MIRType::Symbol:
     339             :       case MIRType::Object:
     340         161 :         break;
     341             : 
     342             :       case MIRType::String:
     343             :       {
     344           6 :         MStringLength* length = MStringLength::New(alloc, op);
     345           6 :         ins->block()->insertBefore(ins, length);
     346           6 :         ins->replaceOperand(0, length);
     347           6 :         break;
     348             :       }
     349             : 
     350             :       default:
     351           0 :         ins->replaceOperand(0, BoxAt(alloc, ins, op));
     352           0 :         break;
     353             :     }
     354         167 :     return true;
     355             : }
     356             : 
     357             : bool
     358           4 : BitwisePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     359             : {
     360           4 :     MIRType specialization = ins->typePolicySpecialization();
     361           4 :     if (specialization == MIRType::None)
     362           0 :         return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
     363             : 
     364           4 :     MOZ_ASSERT(ins->type() == specialization);
     365           4 :     MOZ_ASSERT(specialization == MIRType::Int32 || specialization == MIRType::Double);
     366             : 
     367             :     // This policy works for both unary and binary bitwise operations.
     368           8 :     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
     369           4 :         MDefinition* in = ins->getOperand(i);
     370           4 :         if (in->type() == MIRType::Int32)
     371           2 :             continue;
     372             : 
     373           2 :         MInstruction* replace = MTruncateToInt32::New(alloc, in);
     374           2 :         ins->block()->insertBefore(ins, replace);
     375           2 :         ins->replaceOperand(i, replace);
     376             : 
     377           2 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
     378           0 :             return false;
     379             :     }
     380             : 
     381           4 :     return true;
     382             : }
     383             : 
     384             : bool
     385           0 : PowPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     386             : {
     387           0 :     MIRType specialization = ins->typePolicySpecialization();
     388           0 :     MOZ_ASSERT(specialization == MIRType::Int32 ||
     389             :                specialization == MIRType::Double ||
     390             :                specialization == MIRType::None);
     391             : 
     392             :     // Inputs will be boxed if either is non-numeric.
     393           0 :     if (specialization == MIRType::None)
     394           0 :         return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
     395             : 
     396             :     // Otherwise, input must be a double.
     397           0 :     if (!DoublePolicy<0>::staticAdjustInputs(alloc, ins))
     398           0 :         return false;
     399             : 
     400             :     // Power may be an int32 or a double. Integers receive a faster path.
     401           0 :     if (specialization == MIRType::Double)
     402           0 :         return DoublePolicy<1>::staticAdjustInputs(alloc, ins);
     403           0 :     return IntPolicy<1>::staticAdjustInputs(alloc, ins);
     404             : }
     405             : 
     406             : template <unsigned Op>
     407             : bool
     408          11 : StringPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     409             : {
     410          11 :     MDefinition* in = ins->getOperand(Op);
     411          11 :     if (in->type() == MIRType::String)
     412          11 :         return true;
     413             : 
     414           0 :     MUnbox* replace = MUnbox::New(alloc, in, MIRType::String, MUnbox::Fallible);
     415           0 :     ins->block()->insertBefore(ins, replace);
     416           0 :     ins->replaceOperand(Op, replace);
     417             : 
     418           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     419             : }
     420             : 
     421             : template bool StringPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     422             : template bool StringPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     423             : template bool StringPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     424             : 
     425             : template <unsigned Op>
     426             : bool
     427          24 : ConvertToStringPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     428             : {
     429          24 :     MDefinition* in = ins->getOperand(Op);
     430          24 :     if (in->type() == MIRType::String)
     431          20 :         return true;
     432             : 
     433           4 :     MToString* replace = MToString::New(alloc, in);
     434           4 :     ins->block()->insertBefore(ins, replace);
     435           4 :     ins->replaceOperand(Op, replace);
     436             : 
     437           4 :     if (!ToStringPolicy::staticAdjustInputs(alloc, replace))
     438           0 :         return false;
     439             : 
     440           4 :     return true;
     441             : }
     442             : 
     443             : template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     444             : template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     445             : template bool ConvertToStringPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     446             : 
     447             : template <unsigned Op>
     448             : bool
     449           0 : BooleanPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     450             : {
     451           0 :     MDefinition* in = def->getOperand(Op);
     452           0 :     if (in->type() == MIRType::Boolean)
     453           0 :         return true;
     454             : 
     455           0 :     MUnbox* replace = MUnbox::New(alloc, in, MIRType::Boolean, MUnbox::Fallible);
     456           0 :     def->block()->insertBefore(def, replace);
     457           0 :     def->replaceOperand(Op, replace);
     458             : 
     459           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     460             : }
     461             : 
     462             : template bool BooleanPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     463             : 
     464             : template <unsigned Op>
     465             : bool
     466          20 : IntPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     467             : {
     468          20 :     MDefinition* in = def->getOperand(Op);
     469          20 :     if (in->type() == MIRType::Int32)
     470          20 :         return true;
     471             : 
     472           0 :     MUnbox* replace = MUnbox::New(alloc, in, MIRType::Int32, MUnbox::Fallible);
     473           0 :     def->block()->insertBefore(def, replace);
     474           0 :     def->replaceOperand(Op, replace);
     475             : 
     476           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     477             : }
     478             : 
     479             : template bool IntPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     480             : template bool IntPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     481             : template bool IntPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     482             : template bool IntPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     483             : 
     484             : template <unsigned Op>
     485             : bool
     486           5 : ConvertToInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     487             : {
     488           5 :     MDefinition* in = def->getOperand(Op);
     489           5 :     if (in->type() == MIRType::Int32)
     490           5 :         return true;
     491             : 
     492           0 :     MToInt32* replace = MToInt32::New(alloc, in);
     493           0 :     def->block()->insertBefore(def, replace);
     494           0 :     def->replaceOperand(Op, replace);
     495             : 
     496           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     497             : }
     498             : 
     499             : template bool ConvertToInt32Policy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     500             : 
     501             : template <unsigned Op>
     502             : bool
     503           0 : TruncateToInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     504             : {
     505           0 :     MDefinition* in = def->getOperand(Op);
     506           0 :     if (in->type() == MIRType::Int32)
     507           0 :         return true;
     508             : 
     509           0 :     MTruncateToInt32* replace = MTruncateToInt32::New(alloc, in);
     510           0 :     def->block()->insertBefore(def, replace);
     511           0 :     def->replaceOperand(Op, replace);
     512             : 
     513           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     514             : }
     515             : 
     516             : template bool TruncateToInt32Policy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     517             : template bool TruncateToInt32Policy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     518             : 
     519             : template <unsigned Op>
     520             : bool
     521           0 : DoublePolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     522             : {
     523           0 :     MDefinition* in = def->getOperand(Op);
     524           0 :     if (in->type() == MIRType::Double || in->type() == MIRType::SinCosDouble)
     525           0 :         return true;
     526             : 
     527           0 :     MToDouble* replace = MToDouble::New(alloc, in);
     528           0 :     def->block()->insertBefore(def, replace);
     529           0 :     def->replaceOperand(Op, replace);
     530             : 
     531           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     532             : }
     533             : 
     534             : template bool DoublePolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     535             : template bool DoublePolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     536             : 
     537             : template <unsigned Op>
     538             : bool
     539           0 : Float32Policy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     540             : {
     541           0 :     MDefinition* in = def->getOperand(Op);
     542           0 :     if (in->type() == MIRType::Float32)
     543           0 :         return true;
     544             : 
     545           0 :     MToFloat32* replace = MToFloat32::New(alloc, in);
     546           0 :     def->block()->insertBefore(def, replace);
     547           0 :     def->replaceOperand(Op, replace);
     548             : 
     549           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     550             : }
     551             : 
     552             : template bool Float32Policy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     553             : template bool Float32Policy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     554             : template bool Float32Policy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     555             : 
     556             : template <unsigned Op>
     557             : bool
     558           0 : FloatingPointPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* def)
     559             : {
     560           0 :     MIRType policyType = def->typePolicySpecialization();
     561           0 :     if (policyType == MIRType::Double)
     562           0 :         return DoublePolicy<Op>::staticAdjustInputs(alloc, def);
     563           0 :     return Float32Policy<Op>::staticAdjustInputs(alloc, def);
     564             : }
     565             : 
     566             : template bool FloatingPointPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* def);
     567             : 
     568             : template <unsigned Op>
     569             : bool
     570          53 : NoFloatPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
     571             : {
     572          53 :     EnsureOperandNotFloat32(alloc, def, Op);
     573          53 :     return true;
     574             : }
     575             : 
     576             : template bool NoFloatPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     577             : template bool NoFloatPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     578             : template bool NoFloatPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     579             : template bool NoFloatPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     580             : 
     581             : template <unsigned FirstOp>
     582             : bool
     583          69 : NoFloatPolicyAfter<FirstOp>::adjustInputs(TempAllocator& alloc, MInstruction* def)
     584             : {
     585         240 :     for (size_t op = FirstOp, e = def->numOperands(); op < e; op++)
     586         171 :         EnsureOperandNotFloat32(alloc, def, op);
     587          69 :     return true;
     588             : }
     589             : 
     590             : template bool NoFloatPolicyAfter<1>::adjustInputs(TempAllocator& alloc, MInstruction* def);
     591             : template bool NoFloatPolicyAfter<2>::adjustInputs(TempAllocator& alloc, MInstruction* def);
     592             : 
     593             : template <unsigned Op>
     594             : bool
     595           0 : SimdScalarPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     596             : {
     597           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
     598           0 :     MIRType laneType = SimdTypeToLaneType(ins->type());
     599             : 
     600           0 :     MDefinition* in = ins->getOperand(Op);
     601             : 
     602             :     // A vector with boolean lanes requires Int32 inputs that have already been
     603             :     // converted to 0/-1.
     604             :     // We can't insert a MIRType::Boolean lane directly - it requires conversion.
     605           0 :     if (laneType == MIRType::Boolean) {
     606           0 :         MOZ_ASSERT(in->type() == MIRType::Int32, "Boolean SIMD vector requires Int32 lanes.");
     607           0 :         return true;
     608             :     }
     609             : 
     610           0 :     if (in->type() == laneType)
     611           0 :         return true;
     612             : 
     613             :     MInstruction* replace;
     614           0 :     if (laneType == MIRType::Int32) {
     615           0 :         replace = MTruncateToInt32::New(alloc, in);
     616             :     } else {
     617           0 :         MOZ_ASSERT(laneType == MIRType::Float32);
     618           0 :         replace = MToFloat32::New(alloc, in);
     619             :     }
     620             : 
     621           0 :     ins->block()->insertBefore(ins, replace);
     622           0 :     ins->replaceOperand(Op, replace);
     623             : 
     624           0 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     625             : }
     626             : 
     627             : template bool SimdScalarPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     628             : template bool SimdScalarPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     629             : template bool SimdScalarPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     630             : template bool SimdScalarPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
     631             : 
     632             : template <unsigned Op>
     633             : bool
     634           1 : BoxPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     635             : {
     636           1 :     MDefinition* in = ins->getOperand(Op);
     637           1 :     if (in->type() == MIRType::Value)
     638           1 :         return true;
     639             : 
     640           0 :     ins->replaceOperand(Op, BoxAt(alloc, ins, in));
     641           0 :     return true;
     642             : }
     643             : 
     644             : template bool BoxPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     645             : template bool BoxPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     646             : template bool BoxPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     647             : 
     648             : template <unsigned Op, MIRType Type>
     649             : bool
     650          26 : BoxExceptPolicy<Op, Type>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     651             : {
     652          26 :     MDefinition* in = ins->getOperand(Op);
     653          26 :     if (in->type() == Type)
     654          26 :         return true;
     655           0 :     return BoxPolicy<Op>::staticAdjustInputs(alloc, ins);
     656             : }
     657             : 
     658             : template bool BoxExceptPolicy<0, MIRType::Object>::staticAdjustInputs(TempAllocator& alloc,
     659             :                                                                      MInstruction* ins);
     660             : 
     661             : template <unsigned Op>
     662             : bool
     663          34 : CacheIdPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     664             : {
     665          34 :     MDefinition* in = ins->getOperand(Op);
     666          34 :     switch (in->type()) {
     667             :       case MIRType::Int32:
     668             :       case MIRType::String:
     669             :       case MIRType::Symbol:
     670          33 :         return true;
     671             :       default:
     672           1 :         return BoxPolicy<Op>::staticAdjustInputs(alloc, ins);
     673             :     }
     674             : }
     675             : 
     676             : template bool CacheIdPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     677             : template bool CacheIdPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     678             : 
     679             : bool
     680           0 : ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     681             : {
     682           0 :     MOZ_ASSERT(ins->isToDouble() || ins->isToFloat32());
     683             : 
     684           0 :     MDefinition* in = ins->getOperand(0);
     685             :     MToFPInstruction::ConversionKind conversion;
     686           0 :     if (ins->isToDouble())
     687           0 :         conversion = ins->toToDouble()->conversion();
     688             :     else
     689           0 :         conversion = ins->toToFloat32()->conversion();
     690             : 
     691           0 :     switch (in->type()) {
     692             :       case MIRType::Int32:
     693             :       case MIRType::Float32:
     694             :       case MIRType::Double:
     695             :       case MIRType::Value:
     696             :         // No need for boxing for these types.
     697           0 :         return true;
     698             :       case MIRType::Null:
     699             :         // No need for boxing, when we will convert.
     700           0 :         if (conversion == MToFPInstruction::NonStringPrimitives)
     701           0 :             return true;
     702           0 :         break;
     703             :       case MIRType::Undefined:
     704             :       case MIRType::Boolean:
     705             :         // No need for boxing, when we will convert.
     706           0 :         if (conversion == MToFPInstruction::NonStringPrimitives)
     707           0 :             return true;
     708           0 :         if (conversion == MToFPInstruction::NonNullNonStringPrimitives)
     709           0 :             return true;
     710           0 :         break;
     711             :       case MIRType::Object:
     712             :       case MIRType::String:
     713             :       case MIRType::Symbol:
     714             :         // Objects might be effectful. Symbols give TypeError.
     715           0 :         break;
     716             :       default:
     717           0 :         break;
     718             :     }
     719             : 
     720           0 :     in = BoxAt(alloc, ins, in);
     721           0 :     ins->replaceOperand(0, in);
     722           0 :     return true;
     723             : }
     724             : 
     725             : bool
     726          15 : ToInt32Policy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     727             : {
     728          15 :     MOZ_ASSERT(ins->isToInt32() || ins->isTruncateToInt32());
     729             : 
     730          15 :     MacroAssembler::IntConversionInputKind conversion = MacroAssembler::IntConversion_Any;
     731          15 :     if (ins->isToInt32())
     732          13 :         conversion = ins->toToInt32()->conversion();
     733             : 
     734          15 :     MDefinition* in = ins->getOperand(0);
     735          15 :     switch (in->type()) {
     736             :       case MIRType::Int32:
     737             :       case MIRType::Float32:
     738             :       case MIRType::Double:
     739             :       case MIRType::Value:
     740             :         // No need for boxing for these types.
     741          14 :         return true;
     742             :       case MIRType::Undefined:
     743             :         // No need for boxing when truncating.
     744           1 :         if (ins->isTruncateToInt32())
     745           1 :             return true;
     746           0 :         break;
     747             :       case MIRType::Null:
     748             :         // No need for boxing, when we will convert.
     749           0 :         if (conversion == MacroAssembler::IntConversion_Any)
     750           0 :             return true;
     751           0 :         break;
     752             :       case MIRType::Boolean:
     753             :         // No need for boxing, when we will convert.
     754           0 :         if (conversion == MacroAssembler::IntConversion_Any)
     755           0 :             return true;
     756           0 :         if (conversion == MacroAssembler::IntConversion_NumbersOrBoolsOnly)
     757           0 :             return true;
     758           0 :         break;
     759             :       case MIRType::Object:
     760             :       case MIRType::String:
     761             :       case MIRType::Symbol:
     762             :         // Objects might be effectful. Symbols give TypeError.
     763           0 :         break;
     764             :       default:
     765           0 :         break;
     766             :     }
     767             : 
     768           0 :     in = BoxAt(alloc, ins, in);
     769           0 :     ins->replaceOperand(0, in);
     770           0 :     return true;
     771             : }
     772             : 
     773             : bool
     774           4 : ToStringPolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     775             : {
     776           4 :     MOZ_ASSERT(ins->isToString());
     777             : 
     778           4 :     MIRType type = ins->getOperand(0)->type();
     779           4 :     if (type == MIRType::Object || type == MIRType::Symbol) {
     780           0 :         ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
     781           0 :         return true;
     782             :     }
     783             : 
     784             :     // TODO remove the following line once 966957 has landed
     785           4 :     EnsureOperandNotFloat32(alloc, ins, 0);
     786             : 
     787           4 :     return true;
     788             : }
     789             : 
     790             : template <unsigned Op>
     791             : bool
     792         173 : ObjectPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     793             : {
     794         173 :     MDefinition* in = ins->getOperand(Op);
     795         190 :     if (in->type() == MIRType::Object || in->type() == MIRType::Slots ||
     796          17 :         in->type() == MIRType::Elements)
     797             :     {
     798         165 :         return true;
     799             :     }
     800             : 
     801           8 :     MUnbox* replace = MUnbox::New(alloc, in, MIRType::Object, MUnbox::Fallible);
     802           8 :     ins->block()->insertBefore(ins, replace);
     803           8 :     ins->replaceOperand(Op, replace);
     804             : 
     805           8 :     return replace->typePolicy()->adjustInputs(alloc, replace);
     806             : }
     807             : 
     808             : template bool ObjectPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     809             : template bool ObjectPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     810             : template bool ObjectPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     811             : template bool ObjectPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     812             : 
     813             : template <unsigned Op>
     814             : bool
     815           0 : SimdSameAsReturnedTypePolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
     816             : {
     817           0 :     MOZ_ASSERT(ins->type() == ins->getOperand(Op)->type());
     818           0 :     return true;
     819             : }
     820             : 
     821             : template bool
     822             : SimdSameAsReturnedTypePolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     823             : template bool
     824             : SimdSameAsReturnedTypePolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
     825             : 
     826             : bool
     827           0 : SimdAllPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     828             : {
     829           0 :     for (unsigned i = 0, e = ins->numOperands(); i < e; i++)
     830           0 :         MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
     831           0 :     return true;
     832             : }
     833             : 
     834             : template <unsigned Op>
     835             : bool
     836           0 : SimdPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     837             : {
     838           0 :     MOZ_ASSERT(ins->typePolicySpecialization() == ins->getOperand(Op)->type());
     839           0 :     return true;
     840             : }
     841             : 
     842             : template bool
     843             : SimdPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* ins);
     844             : 
     845             : bool
     846           0 : SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     847             : {
     848           0 :     MSimdGeneralShuffle* s = ins->toSimdGeneralShuffle();
     849             : 
     850           0 :     for (unsigned i = 0; i < s->numVectors(); i++)
     851           0 :         MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
     852             : 
     853             :     // Next inputs are the lanes, which need to be int32
     854           0 :     for (unsigned i = 0; i < s->numLanes(); i++) {
     855           0 :         MDefinition* in = ins->getOperand(s->numVectors() + i);
     856           0 :         if (in->type() == MIRType::Int32)
     857           0 :             continue;
     858             : 
     859           0 :         MInstruction* replace = MToInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly);
     860           0 :         ins->block()->insertBefore(ins, replace);
     861           0 :         ins->replaceOperand(s->numVectors() + i, replace);
     862           0 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
     863           0 :             return false;
     864             :     }
     865             : 
     866           0 :     return true;
     867             : }
     868             : 
     869             : bool
     870           0 : SimdSelectPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     871             : {
     872             :     // First input is the mask, which has to be a boolean.
     873           0 :     MOZ_ASSERT(IsBooleanSimdType(ins->getOperand(0)->type()));
     874             : 
     875             :     // Next inputs are the two vectors of a particular type.
     876           0 :     for (unsigned i = 1; i < 3; i++)
     877           0 :         MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
     878             : 
     879           0 :     return true;
     880             : }
     881             : 
     882             : bool
     883          30 : CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     884             : {
     885          30 :     MCall* call = ins->toCall();
     886             : 
     887          30 :     MDefinition* func = call->getFunction();
     888          30 :     if (func->type() != MIRType::Object) {
     889           7 :         MInstruction* unbox = MUnbox::New(alloc, func, MIRType::Object, MUnbox::Fallible);
     890           7 :         call->block()->insertBefore(call, unbox);
     891           7 :         call->replaceFunction(unbox);
     892             : 
     893           7 :         if (!unbox->typePolicy()->adjustInputs(alloc, unbox))
     894           0 :             return false;
     895             :     }
     896             : 
     897         111 :     for (uint32_t i = 0; i < call->numStackArgs(); i++) {
     898          81 :         if (!alloc.ensureBallast())
     899           0 :             return false;
     900          81 :         EnsureOperandNotFloat32(alloc, call, MCall::IndexOfStackArg(i));
     901             :     }
     902             : 
     903          30 :     return true;
     904             : }
     905             : 
     906             : bool
     907           0 : CallSetElementPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
     908             : {
     909             :     // The first operand should be an object.
     910           0 :     if (!SingleObjectPolicy::staticAdjustInputs(alloc, ins))
     911           0 :         return false;
     912             : 
     913             :     // Box the index and value operands.
     914           0 :     for (size_t i = 1, e = ins->numOperands(); i < e; i++) {
     915           0 :         MDefinition* in = ins->getOperand(i);
     916           0 :         if (in->type() == MIRType::Value)
     917           0 :             continue;
     918           0 :         ins->replaceOperand(i, BoxAt(alloc, ins, in));
     919             :     }
     920           0 :     return true;
     921             : }
     922             : 
     923             : bool
     924           0 : InstanceOfPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
     925             : {
     926             :     // Box first operand if it isn't object
     927           0 :     if (def->getOperand(0)->type() != MIRType::Object)
     928           0 :         if (!BoxPolicy<0>::staticAdjustInputs(alloc, def))
     929           0 :             return false;
     930             : 
     931           0 :     return true;
     932             : }
     933             : 
     934             : bool
     935           0 : StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc, MInstruction* ins,
     936             :                                            Scalar::Type writeType, MDefinition* value,
     937             :                                            int valueOperand)
     938             : {
     939             :     // Storing a SIMD value requires a valueOperand that has already been
     940             :     // SimdUnboxed. See IonBuilder::inlineSimdStore(()
     941           0 :     if (Scalar::isSimdType(writeType)) {
     942           0 :         MOZ_ASSERT(IsSimdType(value->type()));
     943           0 :         return true;
     944             :     }
     945             : 
     946           0 :     MDefinition* curValue = value;
     947             :     // First, ensure the value is int32, boolean, double or Value.
     948             :     // The conversion is based on TypedArrayObjectTemplate::setElementTail.
     949           0 :     switch (value->type()) {
     950             :       case MIRType::Int32:
     951             :       case MIRType::Double:
     952             :       case MIRType::Float32:
     953             :       case MIRType::Boolean:
     954             :       case MIRType::Value:
     955           0 :         break;
     956             :       case MIRType::Null:
     957           0 :         value->setImplicitlyUsedUnchecked();
     958           0 :         value = MConstant::New(alloc, Int32Value(0));
     959           0 :         ins->block()->insertBefore(ins, value->toInstruction());
     960           0 :         break;
     961             :       case MIRType::Undefined:
     962           0 :         value->setImplicitlyUsedUnchecked();
     963           0 :         value = MConstant::New(alloc, DoubleNaNValue());
     964           0 :         ins->block()->insertBefore(ins, value->toInstruction());
     965           0 :         break;
     966             :       case MIRType::Object:
     967             :       case MIRType::String:
     968             :       case MIRType::Symbol:
     969           0 :         value = BoxAt(alloc, ins, value);
     970           0 :         break;
     971             :       default:
     972           0 :         MOZ_CRASH("Unexpected type");
     973             :     }
     974             : 
     975           0 :     if (value != curValue) {
     976           0 :         ins->replaceOperand(valueOperand, value);
     977           0 :         curValue = value;
     978             :     }
     979             : 
     980           0 :     MOZ_ASSERT(value->type() == MIRType::Int32 ||
     981             :                value->type() == MIRType::Boolean ||
     982             :                value->type() == MIRType::Double ||
     983             :                value->type() == MIRType::Float32 ||
     984             :                value->type() == MIRType::Value);
     985             : 
     986           0 :     switch (writeType) {
     987             :       case Scalar::Int8:
     988             :       case Scalar::Uint8:
     989             :       case Scalar::Int16:
     990             :       case Scalar::Uint16:
     991             :       case Scalar::Int32:
     992             :       case Scalar::Uint32:
     993           0 :         if (value->type() != MIRType::Int32) {
     994           0 :             value = MTruncateToInt32::New(alloc, value);
     995           0 :             ins->block()->insertBefore(ins, value->toInstruction());
     996             :         }
     997           0 :         break;
     998             :       case Scalar::Uint8Clamped:
     999             :         // IonBuilder should have inserted ClampToUint8.
    1000           0 :         MOZ_ASSERT(value->type() == MIRType::Int32);
    1001           0 :         break;
    1002             :       case Scalar::Float32:
    1003           0 :         if (value->type() != MIRType::Float32) {
    1004           0 :             value = MToFloat32::New(alloc, value);
    1005           0 :             ins->block()->insertBefore(ins, value->toInstruction());
    1006             :         }
    1007           0 :         break;
    1008             :       case Scalar::Float64:
    1009           0 :         if (value->type() != MIRType::Double) {
    1010           0 :             value = MToDouble::New(alloc, value);
    1011           0 :             ins->block()->insertBefore(ins, value->toInstruction());
    1012             :         }
    1013           0 :         break;
    1014             :       default:
    1015           0 :         MOZ_CRASH("Invalid array type");
    1016             :     }
    1017             : 
    1018           0 :     if (value != curValue)
    1019           0 :         ins->replaceOperand(valueOperand, value);
    1020             : 
    1021           0 :     return true;
    1022             : }
    1023             : 
    1024             : bool
    1025           0 : StoreUnboxedScalarPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1026             : {
    1027           0 :     if (!SingleObjectPolicy::staticAdjustInputs(alloc, ins))
    1028           0 :         return false;
    1029             : 
    1030           0 :     MStoreUnboxedScalar* store = ins->toStoreUnboxedScalar();
    1031           0 :     MOZ_ASSERT(IsValidElementsType(store->elements(), store->offsetAdjustment()));
    1032           0 :     MOZ_ASSERT(store->index()->type() == MIRType::Int32);
    1033             : 
    1034           0 :     return adjustValueInput(alloc, store, store->writeType(), store->value(), 2);
    1035             : }
    1036             : 
    1037             : bool
    1038           0 : StoreTypedArrayHolePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1039             : {
    1040           0 :     MStoreTypedArrayElementHole* store = ins->toStoreTypedArrayElementHole();
    1041           0 :     MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
    1042           0 :     MOZ_ASSERT(store->index()->type() == MIRType::Int32);
    1043           0 :     MOZ_ASSERT(store->length()->type() == MIRType::Int32);
    1044             : 
    1045           0 :     return StoreUnboxedScalarPolicy::adjustValueInput(alloc, ins, store->arrayType(), store->value(), 3);
    1046             : }
    1047             : 
    1048             : bool
    1049           0 : StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1050             : {
    1051           0 :     MStoreTypedArrayElementStatic* store = ins->toStoreTypedArrayElementStatic();
    1052             : 
    1053           0 :     return ConvertToInt32Policy<0>::staticAdjustInputs(alloc, ins) &&
    1054           0 :         StoreUnboxedScalarPolicy::adjustValueInput(alloc, ins, store->accessType(), store->value(), 1);
    1055             : }
    1056             : 
    1057             : bool
    1058           0 : StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1059             : {
    1060           0 :     if (!ObjectPolicy<0>::staticAdjustInputs(alloc, ins))
    1061           0 :         return false;
    1062             : 
    1063           0 :     if (!ObjectPolicy<3>::staticAdjustInputs(alloc, ins))
    1064           0 :         return false;
    1065             : 
    1066             :     // Change the value input to a ToObjectOrNull instruction if it might be
    1067             :     // a non-null primitive. Insert a post barrier for the instruction's object
    1068             :     // and whatever its new value is, unless the value is definitely null.
    1069           0 :     MStoreUnboxedObjectOrNull* store = ins->toStoreUnboxedObjectOrNull();
    1070             : 
    1071           0 :     MOZ_ASSERT(store->typedObj()->type() == MIRType::Object);
    1072             : 
    1073           0 :     MDefinition* value = store->value();
    1074           0 :     if (value->type() == MIRType::Object ||
    1075           0 :         value->type() == MIRType::Null ||
    1076           0 :         value->type() == MIRType::ObjectOrNull)
    1077             :     {
    1078           0 :         if (value->type() != MIRType::Null) {
    1079           0 :             MInstruction* barrier = MPostWriteBarrier::New(alloc, store->typedObj(), value);
    1080           0 :             store->block()->insertBefore(store, barrier);
    1081             :         }
    1082           0 :         return true;
    1083             :     }
    1084             : 
    1085           0 :     MToObjectOrNull* replace = MToObjectOrNull::New(alloc, value);
    1086           0 :     store->block()->insertBefore(store, replace);
    1087           0 :     store->setValue(replace);
    1088             : 
    1089           0 :     if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace))
    1090           0 :         return false;
    1091             : 
    1092           0 :     MInstruction* barrier = MPostWriteBarrier::New(alloc, store->typedObj(), replace);
    1093           0 :     store->block()->insertBefore(store, barrier);
    1094             : 
    1095           0 :     return true;
    1096             : }
    1097             : 
    1098             : bool
    1099           0 : ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1100             : {
    1101           0 :     MDefinition* in = ins->toClampToUint8()->input();
    1102             : 
    1103           0 :     switch (in->type()) {
    1104             :       case MIRType::Int32:
    1105             :       case MIRType::Double:
    1106             :       case MIRType::Value:
    1107           0 :         break;
    1108             :       default:
    1109           0 :           ins->replaceOperand(0, BoxAt(alloc, ins, in));
    1110           0 :         break;
    1111             :     }
    1112             : 
    1113           0 :     return true;
    1114             : }
    1115             : 
    1116             : bool
    1117          18 : FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
    1118             : {
    1119          18 :     MOZ_ASSERT(ins->numOperands() == 1);
    1120          18 :     MIRType inputType = ins->getOperand(0)->type();
    1121          18 :     MIRType outputType = ins->type();
    1122             : 
    1123             :     // Special case when output is a Float32, but input isn't.
    1124          18 :     if (outputType == MIRType::Float32 && inputType != MIRType::Float32) {
    1125             :         // Create a MToFloat32 to add between the MFilterTypeSet and
    1126             :         // its uses.
    1127           0 :         MInstruction* replace = MToFloat32::New(alloc, ins);
    1128           0 :         ins->justReplaceAllUsesWithExcept(replace);
    1129           0 :         ins->block()->insertAfter(ins, replace);
    1130             : 
    1131             :         // Reset the type to not MIRType::Float32
    1132             :         // Note: setResultType shouldn't happen in TypePolicies,
    1133             :         //       Here it is fine, since there is just one use we just
    1134             :         //       added ourself. And the resulting type after MToFloat32
    1135             :         //       equals the original type.
    1136           0 :         ins->setResultType(ins->resultTypeSet()->getKnownMIRType());
    1137           0 :         outputType = ins->type();
    1138             : 
    1139             :         // Do the type analysis
    1140           0 :         if (!replace->typePolicy()->adjustInputs(alloc, replace))
    1141           0 :             return false;
    1142             : 
    1143             :         // Fall through to let the MFilterTypeSet adjust its input based
    1144             :         // on its new type.
    1145             :     }
    1146             : 
    1147             :     // Input and output type are already in accordance.
    1148          18 :     if (inputType == outputType)
    1149           0 :         return true;
    1150             : 
    1151             :     // Output is a value, box the input.
    1152          18 :     if (outputType == MIRType::Value) {
    1153           2 :         MOZ_ASSERT(inputType != MIRType::Value);
    1154           2 :         ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
    1155           2 :         return true;
    1156             :     }
    1157             : 
    1158             :     // The outputType should be a subset of the inputType else we are in code
    1159             :     // that has never executed yet. Bail to see the new type (if that hasn't
    1160             :     // happened yet).
    1161          16 :     if (inputType != MIRType::Value) {
    1162           0 :         MBail* bail = MBail::New(alloc);
    1163           0 :         ins->block()->insertBefore(ins, bail);
    1164           0 :         bail->setDependency(ins->dependency());
    1165           0 :         ins->setDependency(bail);
    1166           0 :         ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
    1167             :     }
    1168             : 
    1169             :     // We can't unbox a value to null/undefined/lazyargs. So keep output
    1170             :     // also a value.
    1171             :     // Note: Using setResultType shouldn't be done in TypePolicies,
    1172             :     //       Here it is fine, since the type barrier has no uses.
    1173          16 :     if (IsNullOrUndefined(outputType) || outputType == MIRType::MagicOptimizedArguments) {
    1174           0 :         MOZ_ASSERT(!ins->hasDefUses());
    1175           0 :         ins->setResultType(MIRType::Value);
    1176           0 :         return true;
    1177             :     }
    1178             : 
    1179             :     // Unbox / propagate the right type.
    1180          16 :     MUnbox::Mode mode = MUnbox::Infallible;
    1181          16 :     MInstruction* replace = MUnbox::New(alloc, ins->getOperand(0), ins->type(), mode);
    1182             : 
    1183          16 :     ins->block()->insertBefore(ins, replace);
    1184          16 :     ins->replaceOperand(0, replace);
    1185          16 :     if (!replace->typePolicy()->adjustInputs(alloc, replace))
    1186           0 :         return false;
    1187             : 
    1188             :     // Carry over the dependency the MFilterTypeSet had.
    1189          16 :     replace->setDependency(ins->dependency());
    1190             : 
    1191          16 :     return true;
    1192             : }
    1193             : 
    1194             : // Lists of all TypePolicy specializations which are used by MIR Instructions.
    1195             : #define TYPE_POLICY_LIST(_)                     \
    1196             :     _(ArithPolicy)                              \
    1197             :     _(BitwisePolicy)                            \
    1198             :     _(BoxInputsPolicy)                          \
    1199             :     _(CallPolicy)                               \
    1200             :     _(CallSetElementPolicy)                     \
    1201             :     _(ClampPolicy)                              \
    1202             :     _(ComparePolicy)                            \
    1203             :     _(FilterTypeSetPolicy)                      \
    1204             :     _(InstanceOfPolicy)                         \
    1205             :     _(PowPolicy)                                \
    1206             :     _(SimdAllPolicy)                            \
    1207             :     _(SimdSelectPolicy)                         \
    1208             :     _(SimdShufflePolicy)                        \
    1209             :     _(StoreTypedArrayElementStaticPolicy)       \
    1210             :     _(StoreTypedArrayHolePolicy)                \
    1211             :     _(StoreUnboxedScalarPolicy)                 \
    1212             :     _(StoreUnboxedObjectOrNullPolicy)           \
    1213             :     _(TestPolicy)                               \
    1214             :     _(AllDoublePolicy)                          \
    1215             :     _(ToDoublePolicy)                           \
    1216             :     _(ToInt32Policy)                            \
    1217             :     _(ToStringPolicy)                           \
    1218             :     _(TypeBarrierPolicy)
    1219             : 
    1220             : #define TEMPLATE_TYPE_POLICY_LIST(_)                                    \
    1221             :     _(BoxExceptPolicy<0, MIRType::Object>)                              \
    1222             :     _(BoxPolicy<0>)                                                     \
    1223             :     _(ConvertToInt32Policy<0>)                                          \
    1224             :     _(ConvertToStringPolicy<0>)                                         \
    1225             :     _(ConvertToStringPolicy<2>)                                         \
    1226             :     _(DoublePolicy<0>)                                                  \
    1227             :     _(FloatingPointPolicy<0>)                                           \
    1228             :     _(IntPolicy<0>)                                                     \
    1229             :     _(IntPolicy<1>)                                                     \
    1230             :     _(Mix3Policy<ObjectPolicy<0>, StringPolicy<1>, BoxPolicy<2> >) \
    1231             :     _(Mix3Policy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2> >)         \
    1232             :     _(Mix3Policy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2> >)      \
    1233             :     _(Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, BoxPolicy<2> >)         \
    1234             :     _(Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2> >)         \
    1235             :     _(Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2> >) \
    1236             :     _(Mix3Policy<ObjectPolicy<0>, ObjectPolicy<1>, BoxPolicy<2> >)      \
    1237             :     _(Mix3Policy<ObjectPolicy<0>, ObjectPolicy<1>, IntPolicy<2> >)      \
    1238             :     _(Mix3Policy<ObjectPolicy<0>, ObjectPolicy<1>, ObjectPolicy<2> >)   \
    1239             :     _(Mix3Policy<StringPolicy<0>, IntPolicy<1>, IntPolicy<2>>)          \
    1240             :     _(Mix3Policy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2> >)   \
    1241             :     _(Mix3Policy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >)   \
    1242             :     _(Mix3Policy<ObjectPolicy<0>, StringPolicy<1>, IntPolicy<2>>)       \
    1243             :     _(Mix4Policy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2>, IntPolicy<3>>) \
    1244             :     _(Mix4Policy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3> >) \
    1245             :     _(Mix3Policy<ObjectPolicy<0>, CacheIdPolicy<1>, NoFloatPolicy<2>>)  \
    1246             :     _(Mix4Policy<SimdScalarPolicy<0>, SimdScalarPolicy<1>, SimdScalarPolicy<2>, SimdScalarPolicy<3> >) \
    1247             :     _(MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >)                        \
    1248             :     _(MixPolicy<ConvertToStringPolicy<0>, ConvertToStringPolicy<1> >)   \
    1249             :     _(MixPolicy<ConvertToStringPolicy<0>, ObjectPolicy<1> >)            \
    1250             :     _(MixPolicy<DoublePolicy<0>, DoublePolicy<1> >)                     \
    1251             :     _(MixPolicy<IntPolicy<0>, IntPolicy<1> >)                           \
    1252             :     _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >)                        \
    1253             :     _(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, CacheIdPolicy<1>>) \
    1254             :     _(MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1> >)                    \
    1255             :     _(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<1> >)            \
    1256             :     _(MixPolicy<ObjectPolicy<0>, IntPolicy<1> >)                        \
    1257             :     _(MixPolicy<ObjectPolicy<0>, IntPolicy<2> >)                        \
    1258             :     _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<1> >)                    \
    1259             :     _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<2> >)                    \
    1260             :     _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<3> >)                    \
    1261             :     _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >)                     \
    1262             :     _(MixPolicy<ObjectPolicy<0>, StringPolicy<1> >)                     \
    1263             :     _(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<2> >)            \
    1264             :     _(MixPolicy<ObjectPolicy<1>, ConvertToStringPolicy<0> >)            \
    1265             :     _(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdSameAsReturnedTypePolicy<1> >) \
    1266             :     _(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdScalarPolicy<1> >) \
    1267             :     _(MixPolicy<StringPolicy<0>, IntPolicy<1> >)                        \
    1268             :     _(MixPolicy<StringPolicy<0>, StringPolicy<1> >)                     \
    1269             :     _(MixPolicy<BoxPolicy<0>, BoxPolicy<1> >)                           \
    1270             :     _(NoFloatPolicy<0>)                                                 \
    1271             :     _(NoFloatPolicyAfter<1>)                                            \
    1272             :     _(NoFloatPolicyAfter<2>)                                            \
    1273             :     _(ObjectPolicy<0>)                                                  \
    1274             :     _(ObjectPolicy<1>)                                                  \
    1275             :     _(ObjectPolicy<3>)                                                  \
    1276             :     _(SimdPolicy<0>)                                                    \
    1277             :     _(SimdSameAsReturnedTypePolicy<0>)                                  \
    1278             :     _(SimdScalarPolicy<0>)                                              \
    1279             :     _(StringPolicy<0>)
    1280             : 
    1281             : 
    1282             : namespace js {
    1283             : namespace jit {
    1284             : 
    1285             : // Define for all used TypePolicy specialization, the definition for
    1286             : // |TypePolicy::Data::thisTypePolicy|.  This function returns one constant
    1287             : // instance of the TypePolicy which is shared among all MIR Instructions of the
    1288             : // same type.
    1289             : //
    1290             : // This Macro use __VA_ARGS__ to account for commas of template parameters.
    1291             : #define DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_(...)    \
    1292             :     TypePolicy *                                        \
    1293             :     __VA_ARGS__::Data::thisTypePolicy()                 \
    1294             :     {                                                   \
    1295             :         static __VA_ARGS__ singletonType;               \
    1296             :         return &singletonType;                          \
    1297             :     }
    1298             : 
    1299         615 :     TYPE_POLICY_LIST(DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
    1300         301 :     TEMPLATE_TYPE_POLICY_LIST(template<> DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
    1301             : #undef DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_
    1302             : 
    1303             : } // namespace jit
    1304             : } // namespace js
    1305             : 
    1306             : namespace {
    1307             : 
    1308             : // For extra-good measure in case an unqualified use is ever introduced.  (The
    1309             : // main use in the macro below is explicitly qualified so as not to consult
    1310             : // this scope and find this function.)
    1311             : inline TypePolicy*
    1312             : thisTypePolicy() = delete;
    1313             : 
    1314             : static MIRType
    1315           0 : thisTypeSpecialization()
    1316             : {
    1317           0 :     MOZ_CRASH("TypeSpecialization lacks definition of thisTypeSpecialization.");
    1318             : }
    1319             : 
    1320             : } // namespace
    1321             : 
    1322             : // For each MIR Instruction, this macro define the |typePolicy| method which is
    1323             : // using the |thisTypePolicy| method.  The |thisTypePolicy| method is either a
    1324             : // member of the MIR Instruction, such as with MGetElementCache, a member
    1325             : // inherited from the TypePolicy::Data structure, or a member inherited from
    1326             : // NoTypePolicy if the MIR instruction has no type policy.
    1327             : #define DEFINE_MIR_TYPEPOLICY_MEMBERS_(op)      \
    1328             :     TypePolicy *                                \
    1329             :     js::jit::M##op::typePolicy()                \
    1330             :     {                                           \
    1331             :         return M##op::thisTypePolicy();         \
    1332             :     }                                           \
    1333             :                                                 \
    1334             :     MIRType                                     \
    1335             :     js::jit::M##op::typePolicySpecialization()  \
    1336             :     {                                           \
    1337             :         return thisTypeSpecialization();        \
    1338             :     }
    1339             : 
    1340        2439 :     MIR_OPCODE_LIST(DEFINE_MIR_TYPEPOLICY_MEMBERS_)
    1341             : #undef DEFINE_MIR_TYPEPOLICY_MEMBERS_

Generated by: LCOV version 1.13