tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TypePolicy.cpp (46098B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/JitAllocPolicy.h"
     10 #include "jit/MIR-wasm.h"
     11 #include "jit/MIR.h"
     12 #include "jit/MIRGraph.h"
     13 #include "js/ScalarType.h"  // js::Scalar::Type
     14 #include "util/DifferentialTesting.h"
     15 
     16 using namespace js;
     17 using namespace js::jit;
     18 
     19 static void EnsureOperandNotFloat32(TempAllocator& alloc, MInstruction* def,
     20                                    unsigned op) {
     21  MDefinition* in = def->getOperand(op);
     22  if (in->type() == MIRType::Float32) {
     23    MToDouble* replace = MToDouble::New(alloc, in);
     24    def->block()->insertBefore(def, replace);
     25    if (def->isRecoveredOnBailout()) {
     26      replace->setRecoveredOnBailout();
     27    }
     28    def->replaceOperand(op, replace);
     29  }
     30 }
     31 
     32 template <class T>
     33 [[nodiscard]] static bool ConvertOperand(TempAllocator& alloc,
     34                                         MInstruction* def, unsigned op,
     35                                         MIRType expected) {
     36  MDefinition* in = def->getOperand(op);
     37  if (in->type() == expected) {
     38    return true;
     39  }
     40 
     41  auto* replace = T::New(alloc, in);
     42  def->block()->insertBefore(def, replace);
     43  def->replaceOperand(op, replace);
     44 
     45  return replace->typePolicy()->adjustInputs(alloc, replace);
     46 }
     47 
     48 static void SetTypePolicyBailoutKind(MInstruction* newIns,
     49                                     MInstruction* forIns) {
     50  // Infallible ToFloat32 or ToDouble doesn't bail out.
     51  if ((newIns->isToFloat32() || newIns->isToDouble()) && !newIns->isGuard()) {
     52    return;
     53  }
     54 
     55  // Ensure we're not introducing TypePolicy bailouts for transpiled CacheIR
     56  // instructions. Unbox operations and other guards should have been inserted
     57  // by the transpiler.
     58  //
     59  // This avoids a performance cliff because frequent TypePolicy bailouts will
     60  // disable Warp compilation instead of invalidating the script.
     61  // See bug 1850305.
     62  MOZ_ASSERT(forIns->bailoutKind() != BailoutKind::TranspiledCacheIR);
     63 
     64  newIns->setBailoutKind(BailoutKind::TypePolicy);
     65 }
     66 
     67 [[nodiscard]] static bool UnboxOperand(TempAllocator& alloc, MInstruction* def,
     68                                       unsigned op, MIRType expected) {
     69  MDefinition* in = def->getOperand(op);
     70  if (in->type() == expected) {
     71    return true;
     72  }
     73 
     74  auto* replace = MUnbox::New(alloc, in, expected, MUnbox::Fallible);
     75  SetTypePolicyBailoutKind(replace, def);
     76  def->block()->insertBefore(def, replace);
     77  def->replaceOperand(op, replace);
     78 
     79  return replace->typePolicy()->adjustInputs(alloc, replace);
     80 }
     81 
     82 MDefinition* js::jit::BoxAt(TempAllocator& alloc, MInstruction* at,
     83                            MDefinition* operand) {
     84  MDefinition* boxedOperand = operand;
     85  // Replace Float32 by double
     86  if (operand->type() == MIRType::Float32) {
     87    MInstruction* replace = MToDouble::New(alloc, operand);
     88    at->block()->insertBefore(at, replace);
     89    boxedOperand = replace;
     90  }
     91  MBox* box = MBox::New(alloc, boxedOperand);
     92  at->block()->insertBefore(at, box);
     93  return box;
     94 }
     95 
     96 bool BoxInputsPolicy::staticAdjustInputs(TempAllocator& alloc,
     97                                         MInstruction* ins) {
     98  for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
     99    MDefinition* in = ins->getOperand(i);
    100    if (in->type() == MIRType::Value) {
    101      continue;
    102    }
    103    ins->replaceOperand(i, BoxAt(alloc, ins, in));
    104  }
    105  return true;
    106 }
    107 
    108 bool ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
    109  MOZ_ASSERT(IsNumberType(ins->type()));
    110  MOZ_ASSERT(ins->type() == MIRType::Double || ins->type() == MIRType::Int32 ||
    111             ins->type() == MIRType::Float32 || ins->type() == MIRType::IntPtr);
    112 
    113  for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
    114    MDefinition* in = ins->getOperand(i);
    115    if (in->type() == ins->type()) {
    116      continue;
    117    }
    118    MOZ_ASSERT(ins->type() != MIRType::IntPtr,
    119               "conversion to IntPtr not supported");
    120 
    121    MInstruction* replace;
    122 
    123    if (ins->type() == MIRType::Double) {
    124      replace = MToDouble::New(alloc, in);
    125    } else if (ins->type() == MIRType::Float32) {
    126      replace = MToFloat32::New(alloc, in);
    127    } else {
    128      replace = MToNumberInt32::New(alloc, in);
    129    }
    130 
    131    SetTypePolicyBailoutKind(replace, ins);
    132    ins->block()->insertBefore(ins, replace);
    133    ins->replaceOperand(i, replace);
    134 
    135    if (!replace->typePolicy()->adjustInputs(alloc, replace)) {
    136      return false;
    137    }
    138  }
    139 
    140  return true;
    141 }
    142 
    143 bool BigIntArithPolicy::adjustInputs(TempAllocator& alloc,
    144                                     MInstruction* ins) const {
    145  MOZ_ASSERT(ins->type() == MIRType::BigInt);
    146 
    147  for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
    148    if (!ConvertOperand<MToBigInt>(alloc, ins, i, MIRType::BigInt)) {
    149      return false;
    150    }
    151  }
    152 
    153  return true;
    154 }
    155 
    156 bool AllDoublePolicy::staticAdjustInputs(TempAllocator& alloc,
    157                                         MInstruction* ins) {
    158  for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
    159    MDefinition* in = ins->getOperand(i);
    160    if (in->type() == MIRType::Double) {
    161      continue;
    162    }
    163 
    164    if (!alloc.ensureBallast()) {
    165      return false;
    166    }
    167    MInstruction* replace = MToDouble::New(alloc, in);
    168 
    169    ins->block()->insertBefore(ins, replace);
    170    ins->replaceOperand(i, replace);
    171 
    172    if (!replace->typePolicy()->adjustInputs(alloc, replace)) {
    173      return false;
    174    }
    175  }
    176 
    177  return true;
    178 }
    179 
    180 bool ComparePolicy::adjustInputs(TempAllocator& alloc,
    181                                 MInstruction* def) const {
    182  auto convertOperand = [&](size_t index, MIRType expected) {
    183    MDefinition* operand = def->getOperand(index);
    184    if (operand->type() == expected) {
    185      return true;
    186    }
    187    MInstruction* replace = nullptr;
    188    switch (expected) {
    189      case MIRType::Double:
    190        replace = MToDouble::New(alloc, operand);
    191        break;
    192      case MIRType::Int32:
    193        replace = MToNumberInt32::New(alloc, operand);
    194        break;
    195      case MIRType::Float32:
    196        replace = MToFloat32::New(alloc, operand);
    197        break;
    198      case MIRType::String:
    199        replace =
    200            MUnbox::New(alloc, operand, MIRType::String, MUnbox::Fallible);
    201        break;
    202      case MIRType::Symbol:
    203        replace =
    204            MUnbox::New(alloc, operand, MIRType::Symbol, MUnbox::Fallible);
    205        break;
    206      case MIRType::Object:
    207        replace =
    208            MUnbox::New(alloc, operand, MIRType::Object, MUnbox::Fallible);
    209        break;
    210      case MIRType::BigInt:
    211        replace =
    212            MUnbox::New(alloc, operand, MIRType::BigInt, MUnbox::Fallible);
    213        break;
    214      default:
    215        MOZ_CRASH("Unsupported MIRType");
    216    }
    217    replace->setBailoutKind(BailoutKind::TypePolicy);
    218    def->block()->insertBefore(def, replace);
    219    def->replaceOperand(index, replace);
    220    return replace->typePolicy()->adjustInputs(alloc, replace);
    221  };
    222 
    223  MOZ_ASSERT(def->isCompare());
    224  MCompare* compare = def->toCompare();
    225  switch (compare->compareType()) {
    226    case MCompare::Compare_Undefined:
    227    case MCompare::Compare_Null:
    228      MOZ_ASSERT(compare->rhs()->type() == MIRType::Undefined ||
    229                 compare->rhs()->type() == MIRType::Null);
    230      // IF the operand is float32, we must convert it to a double.
    231      if (compare->lhs()->type() == MIRType::Float32) {
    232        MInstruction* replace = MToDouble::New(alloc, compare->lhs());
    233        def->block()->insertBefore(def, replace);
    234        def->replaceOperand(0, replace);
    235        return replace->typePolicy()->adjustInputs(alloc, replace);
    236      }
    237      // GVN and lowering handle all other types.
    238      return true;
    239    case MCompare::Compare_Int32:
    240      return convertOperand(0, MIRType::Int32) &&
    241             convertOperand(1, MIRType::Int32);
    242    case MCompare::Compare_IntPtr:
    243    case MCompare::Compare_UIntPtr:
    244      MOZ_ASSERT(compare->lhs()->type() == MIRType::IntPtr);
    245      MOZ_ASSERT(compare->rhs()->type() == MIRType::IntPtr);
    246      return true;
    247    case MCompare::Compare_Double:
    248      return convertOperand(0, MIRType::Double) &&
    249             convertOperand(1, MIRType::Double);
    250    case MCompare::Compare_Float32:
    251      return convertOperand(0, MIRType::Float32) &&
    252             convertOperand(1, MIRType::Float32);
    253    case MCompare::Compare_String:
    254      return convertOperand(0, MIRType::String) &&
    255             convertOperand(1, MIRType::String);
    256    case MCompare::Compare_Symbol:
    257      return convertOperand(0, MIRType::Symbol) &&
    258             convertOperand(1, MIRType::Symbol);
    259    case MCompare::Compare_Object:
    260      return convertOperand(0, MIRType::Object) &&
    261             convertOperand(1, MIRType::Object);
    262    case MCompare::Compare_BigInt:
    263      return convertOperand(0, MIRType::BigInt) &&
    264             convertOperand(1, MIRType::BigInt);
    265    case MCompare::Compare_BigInt_Int32:
    266      return convertOperand(0, MIRType::BigInt) &&
    267             convertOperand(1, MIRType::Int32);
    268    case MCompare::Compare_BigInt_Double:
    269      return convertOperand(0, MIRType::BigInt) &&
    270             convertOperand(1, MIRType::Double);
    271    case MCompare::Compare_BigInt_String:
    272      return convertOperand(0, MIRType::BigInt) &&
    273             convertOperand(1, MIRType::String);
    274    case MCompare::Compare_UInt32:
    275    case MCompare::Compare_Int64:
    276    case MCompare::Compare_UInt64:
    277    case MCompare::Compare_WasmAnyRef:
    278      break;
    279  }
    280  MOZ_CRASH("Unexpected compare type");
    281 }
    282 
    283 bool TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
    284  MDefinition* op = ins->getOperand(0);
    285  switch (op->type()) {
    286    case MIRType::Value:
    287    case MIRType::Null:
    288    case MIRType::Undefined:
    289    case MIRType::Boolean:
    290    case MIRType::Int32:
    291    case MIRType::Double:
    292    case MIRType::Float32:
    293    case MIRType::Symbol:
    294    case MIRType::BigInt:
    295    case MIRType::Object:
    296      break;
    297 
    298    case MIRType::String: {
    299      MStringLength* length = MStringLength::New(alloc, op);
    300      ins->block()->insertBefore(ins, length);
    301      ins->replaceOperand(0, length);
    302      break;
    303    }
    304 
    305    case MIRType::Int64:
    306    case MIRType::IntPtr:
    307      MOZ_CRASH("Int64 and IntPtr are only used as input type after GVN");
    308 
    309    default:
    310      MOZ_ASSERT(IsMagicType(op->type()));
    311      ins->replaceOperand(0, BoxAt(alloc, ins, op));
    312      break;
    313  }
    314  return true;
    315 }
    316 
    317 bool BitwisePolicy::adjustInputs(TempAllocator& alloc,
    318                                 MInstruction* ins) const {
    319  MOZ_ASSERT(ins->type() == MIRType::Int32 || ins->type() == MIRType::Double ||
    320             ins->type() == MIRType::IntPtr);
    321 
    322  // No type conversion needed when using IntPtr.
    323  if (ins->type() == MIRType::IntPtr) {
    324 #ifdef DEBUG
    325    for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
    326      MOZ_ASSERT(ins->getOperand(i)->type() == MIRType::IntPtr);
    327    }
    328 #endif
    329    return true;
    330  }
    331 
    332  // This policy works for both unary and binary bitwise operations.
    333  for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
    334    if (!ConvertOperand<MTruncateToInt32>(alloc, ins, i, MIRType::Int32)) {
    335      return false;
    336    }
    337  }
    338 
    339  return true;
    340 }
    341 
    342 bool PowPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
    343  MOZ_ASSERT(ins->type() == MIRType::Int32 || ins->type() == MIRType::Double);
    344 
    345  if (ins->type() == MIRType::Int32) {
    346    // Both operands must be int32.
    347    return UnboxedInt32Policy<0>::staticAdjustInputs(alloc, ins) &&
    348           UnboxedInt32Policy<1>::staticAdjustInputs(alloc, ins);
    349  }
    350 
    351  // Otherwise, input must be a double.
    352  if (!DoublePolicy<0>::staticAdjustInputs(alloc, ins)) {
    353    return false;
    354  }
    355 
    356  // Power may be an int32 or a double. Integers receive a faster path.
    357  MDefinition* power = ins->toPow()->power();
    358  if (power->isToDouble()) {
    359    MDefinition* input = power->toToDouble()->input();
    360    if (input->type() == MIRType::Int32) {
    361      power->setImplicitlyUsedUnchecked();
    362      ins->replaceOperand(1, input);
    363      return true;
    364    }
    365  }
    366  return DoublePolicy<1>::staticAdjustInputs(alloc, ins);
    367 }
    368 
    369 bool SignPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
    370  MOZ_ASSERT(ins->isSign());
    371  MIRType specialization = ins->typePolicySpecialization();
    372 
    373  // MSign is specialized for int32 input types.
    374  if (specialization == MIRType::Int32) {
    375    return UnboxedInt32Policy<0>::staticAdjustInputs(alloc, ins);
    376  }
    377 
    378  // Otherwise convert input to double.
    379  MOZ_ASSERT(IsFloatingPointType(specialization));
    380  return DoublePolicy<0>::staticAdjustInputs(alloc, ins);
    381 }
    382 
    383 template <unsigned Op>
    384 bool SymbolPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    385                                          MInstruction* ins) {
    386  return UnboxOperand(alloc, ins, Op, MIRType::Symbol);
    387 }
    388 
    389 template bool SymbolPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    390                                                  MInstruction* ins);
    391 
    392 template <unsigned Op>
    393 bool BooleanPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    394                                           MInstruction* ins) {
    395  return UnboxOperand(alloc, ins, Op, MIRType::Boolean);
    396 }
    397 
    398 template bool BooleanPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    399                                                   MInstruction* ins);
    400 
    401 template <unsigned Op>
    402 bool StringPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    403                                          MInstruction* ins) {
    404  return UnboxOperand(alloc, ins, Op, MIRType::String);
    405 }
    406 
    407 template bool StringPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    408                                                  MInstruction* ins);
    409 template bool StringPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    410                                                  MInstruction* ins);
    411 template bool StringPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    412                                                  MInstruction* ins);
    413 
    414 template <unsigned Op>
    415 bool ConvertToStringPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    416                                                   MInstruction* ins) {
    417  MDefinition* in = ins->getOperand(Op);
    418  if (in->type() == MIRType::String) {
    419    return true;
    420  }
    421 
    422  MToString* replace =
    423      MToString::New(alloc, in, MToString::SideEffectHandling::Bailout);
    424  ins->block()->insertBefore(ins, replace);
    425  ins->replaceOperand(Op, replace);
    426 
    427  return ToStringPolicy::staticAdjustInputs(alloc, replace);
    428 }
    429 
    430 template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    431                                                           MInstruction* ins);
    432 template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    433                                                           MInstruction* ins);
    434 template bool ConvertToStringPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    435                                                           MInstruction* ins);
    436 
    437 template <unsigned Op>
    438 bool BigIntPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    439                                          MInstruction* ins) {
    440  return UnboxOperand(alloc, ins, Op, MIRType::BigInt);
    441 }
    442 
    443 template bool BigIntPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    444                                                  MInstruction* ins);
    445 template bool BigIntPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    446                                                  MInstruction* ins);
    447 
    448 template <unsigned Op>
    449 bool UnboxedInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc,
    450                                                MInstruction* def) {
    451  return UnboxOperand(alloc, def, Op, MIRType::Int32);
    452 }
    453 
    454 template bool UnboxedInt32Policy<0>::staticAdjustInputs(TempAllocator& alloc,
    455                                                        MInstruction* def);
    456 template bool UnboxedInt32Policy<1>::staticAdjustInputs(TempAllocator& alloc,
    457                                                        MInstruction* def);
    458 template bool UnboxedInt32Policy<2>::staticAdjustInputs(TempAllocator& alloc,
    459                                                        MInstruction* def);
    460 template bool UnboxedInt32Policy<3>::staticAdjustInputs(TempAllocator& alloc,
    461                                                        MInstruction* def);
    462 
    463 template <unsigned Op>
    464 bool Int32OrIntPtrPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    465                                                 MInstruction* def) {
    466  MDefinition* in = def->getOperand(Op);
    467  if (in->type() == MIRType::IntPtr) {
    468    return true;
    469  }
    470 
    471  return UnboxedInt32Policy<Op>::staticAdjustInputs(alloc, def);
    472 }
    473 
    474 template bool Int32OrIntPtrPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    475                                                         MInstruction* def);
    476 template bool Int32OrIntPtrPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    477                                                         MInstruction* def);
    478 
    479 template <unsigned Op>
    480 bool IntPtrPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    481                                          MInstruction* def) {
    482  // We don't (yet) support converting other types to IntPtr.
    483  MOZ_ASSERT(def->getOperand(Op)->type() == MIRType::IntPtr);
    484  return true;
    485 }
    486 
    487 template bool IntPtrPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    488                                                  MInstruction* def);
    489 
    490 template bool IntPtrPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    491                                                  MInstruction* def);
    492 
    493 template bool IntPtrPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    494                                                  MInstruction* def);
    495 
    496 template <unsigned Op>
    497 bool ConvertToInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc,
    498                                                  MInstruction* def) {
    499  return ConvertOperand<MToNumberInt32>(alloc, def, Op, MIRType::Int32);
    500 }
    501 
    502 template bool ConvertToInt32Policy<0>::staticAdjustInputs(TempAllocator& alloc,
    503                                                          MInstruction* def);
    504 
    505 template <unsigned Op>
    506 bool TruncateToInt32OrToInt64Policy<Op>::staticAdjustInputs(
    507    TempAllocator& alloc, MInstruction* def) {
    508  MOZ_ASSERT(def->isCompareExchangeTypedArrayElement() ||
    509             def->isAtomicExchangeTypedArrayElement() ||
    510             def->isAtomicTypedArrayElementBinop());
    511 
    512  Scalar::Type type;
    513  if (def->isCompareExchangeTypedArrayElement()) {
    514    type = def->toCompareExchangeTypedArrayElement()->arrayType();
    515  } else if (def->isAtomicExchangeTypedArrayElement()) {
    516    type = def->toAtomicExchangeTypedArrayElement()->arrayType();
    517  } else {
    518    type = def->toAtomicTypedArrayElementBinop()->arrayType();
    519  }
    520 
    521  if (Scalar::isBigIntType(type)) {
    522    return ConvertOperand<MToInt64>(alloc, def, Op, MIRType::Int64);
    523  }
    524  return ConvertOperand<MTruncateToInt32>(alloc, def, Op, MIRType::Int32);
    525 }
    526 
    527 template bool TruncateToInt32OrToInt64Policy<2>::staticAdjustInputs(
    528    TempAllocator& alloc, MInstruction* def);
    529 template bool TruncateToInt32OrToInt64Policy<3>::staticAdjustInputs(
    530    TempAllocator& alloc, MInstruction* def);
    531 
    532 template <unsigned Op>
    533 bool DoublePolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    534                                          MInstruction* def) {
    535  return ConvertOperand<MToDouble>(alloc, def, Op, MIRType::Double);
    536 }
    537 
    538 template bool DoublePolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    539                                                  MInstruction* def);
    540 template bool DoublePolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    541                                                  MInstruction* def);
    542 
    543 template <unsigned Op>
    544 bool Float32Policy<Op>::staticAdjustInputs(TempAllocator& alloc,
    545                                           MInstruction* def) {
    546  return ConvertOperand<MToFloat32>(alloc, def, Op, MIRType::Float32);
    547 }
    548 
    549 template bool Float32Policy<0>::staticAdjustInputs(TempAllocator& alloc,
    550                                                   MInstruction* def);
    551 template bool Float32Policy<1>::staticAdjustInputs(TempAllocator& alloc,
    552                                                   MInstruction* def);
    553 template bool Float32Policy<2>::staticAdjustInputs(TempAllocator& alloc,
    554                                                   MInstruction* def);
    555 
    556 template <unsigned Op>
    557 bool FloatingPointPolicy<Op>::adjustInputs(TempAllocator& alloc,
    558                                           MInstruction* def) const {
    559  MIRType policyType = def->typePolicySpecialization();
    560  if (policyType == MIRType::Double) {
    561    return DoublePolicy<Op>::staticAdjustInputs(alloc, def);
    562  }
    563  return Float32Policy<Op>::staticAdjustInputs(alloc, def);
    564 }
    565 
    566 template bool FloatingPointPolicy<0>::adjustInputs(TempAllocator& alloc,
    567                                                   MInstruction* def) const;
    568 
    569 template <unsigned Op>
    570 bool NoFloatPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    571                                           MInstruction* def) {
    572  EnsureOperandNotFloat32(alloc, def, Op);
    573  return true;
    574 }
    575 
    576 template bool NoFloatPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    577                                                   MInstruction* def);
    578 template bool NoFloatPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    579                                                   MInstruction* def);
    580 template bool NoFloatPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    581                                                   MInstruction* def);
    582 template bool NoFloatPolicy<3>::staticAdjustInputs(TempAllocator& alloc,
    583                                                   MInstruction* def);
    584 
    585 template <unsigned FirstOp>
    586 bool NoFloatPolicyAfter<FirstOp>::staticAdjustInputs(TempAllocator& alloc,
    587                                                     MInstruction* def) {
    588  for (size_t op = FirstOp, e = def->numOperands(); op < e; op++) {
    589    EnsureOperandNotFloat32(alloc, def, op);
    590  }
    591  return true;
    592 }
    593 
    594 template bool NoFloatPolicyAfter<0>::staticAdjustInputs(TempAllocator& alloc,
    595                                                        MInstruction* def);
    596 template bool NoFloatPolicyAfter<1>::staticAdjustInputs(TempAllocator& alloc,
    597                                                        MInstruction* def);
    598 template bool NoFloatPolicyAfter<2>::staticAdjustInputs(TempAllocator& alloc,
    599                                                        MInstruction* def);
    600 
    601 template <unsigned Op>
    602 bool BoxPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    603                                       MInstruction* ins) {
    604  MDefinition* in = ins->getOperand(Op);
    605  if (in->type() == MIRType::Value) {
    606    return true;
    607  }
    608 
    609  ins->replaceOperand(Op, BoxAt(alloc, ins, in));
    610  return true;
    611 }
    612 
    613 template bool BoxPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    614                                               MInstruction* ins);
    615 template bool BoxPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    616                                               MInstruction* ins);
    617 template bool BoxPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    618                                               MInstruction* ins);
    619 
    620 template <unsigned Op, MIRType Type>
    621 bool BoxExceptPolicy<Op, Type>::staticAdjustInputs(TempAllocator& alloc,
    622                                                   MInstruction* ins) {
    623  MDefinition* in = ins->getOperand(Op);
    624  if (in->type() == Type) {
    625    return true;
    626  }
    627  return BoxPolicy<Op>::staticAdjustInputs(alloc, ins);
    628 }
    629 
    630 template bool BoxExceptPolicy<0, MIRType::Object>::staticAdjustInputs(
    631    TempAllocator& alloc, MInstruction* ins);
    632 
    633 template <unsigned Op>
    634 bool CacheIdPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    635                                           MInstruction* ins) {
    636  MDefinition* in = ins->getOperand(Op);
    637  switch (in->type()) {
    638    case MIRType::Int32:
    639    case MIRType::String:
    640    case MIRType::Symbol:
    641      return true;
    642    default:
    643      return BoxPolicy<Op>::staticAdjustInputs(alloc, ins);
    644  }
    645 }
    646 
    647 template bool CacheIdPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    648                                                   MInstruction* ins);
    649 template bool CacheIdPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    650                                                   MInstruction* ins);
    651 
    652 bool ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc,
    653                                        MInstruction* ins) {
    654  MOZ_ASSERT(ins->isToDouble() || ins->isToFloat32() || ins->isToFloat16());
    655 
    656  MDefinition* in = ins->getOperand(0);
    657  switch (in->type()) {
    658    case MIRType::Int32:
    659    case MIRType::Float32:
    660    case MIRType::Double:
    661    case MIRType::Value:
    662    case MIRType::Null:
    663    case MIRType::Undefined:
    664    case MIRType::Boolean:
    665      // No need for boxing for these types.
    666      return true;
    667    case MIRType::Object:
    668    case MIRType::String:
    669    case MIRType::Symbol:
    670    case MIRType::BigInt:
    671      // Objects might be effectful. Symbols and BigInts give TypeError.
    672      break;
    673    default:
    674      break;
    675  }
    676 
    677  in = BoxAt(alloc, ins, in);
    678  ins->replaceOperand(0, in);
    679  return true;
    680 }
    681 
    682 bool ToInt32Policy::staticAdjustInputs(TempAllocator& alloc,
    683                                       MInstruction* ins) {
    684  MOZ_ASSERT(ins->isToNumberInt32() || ins->isTruncateToInt32());
    685 
    686  IntConversionInputKind conversion = IntConversionInputKind::Any;
    687  if (ins->isToNumberInt32()) {
    688    conversion = ins->toToNumberInt32()->conversion();
    689  }
    690 
    691  MDefinition* in = ins->getOperand(0);
    692  switch (in->type()) {
    693    case MIRType::Int32:
    694    case MIRType::Float32:
    695    case MIRType::Double:
    696    case MIRType::Value:
    697      // No need for boxing for these types.
    698      return true;
    699    case MIRType::Undefined:
    700      // No need for boxing when truncating.
    701      if (ins->isTruncateToInt32()) {
    702        return true;
    703      }
    704      break;
    705    case MIRType::Null:
    706      // No need for boxing, when we will convert.
    707      if (conversion == IntConversionInputKind::Any) {
    708        return true;
    709      }
    710      break;
    711    case MIRType::Boolean:
    712      // No need for boxing, when we will convert.
    713      if (conversion == IntConversionInputKind::Any) {
    714        return true;
    715      }
    716      break;
    717    case MIRType::Object:
    718    case MIRType::String:
    719    case MIRType::Symbol:
    720    case MIRType::BigInt:
    721      // Objects might be effectful. Symbols and BigInts give TypeError.
    722      break;
    723    default:
    724      break;
    725  }
    726 
    727  in = BoxAt(alloc, ins, in);
    728  ins->replaceOperand(0, in);
    729  return true;
    730 }
    731 
    732 bool ToBigIntPolicy::staticAdjustInputs(TempAllocator& alloc,
    733                                        MInstruction* ins) {
    734  MOZ_ASSERT(ins->isToBigInt());
    735 
    736  MDefinition* in = ins->getOperand(0);
    737  switch (in->type()) {
    738    case MIRType::BigInt:
    739    case MIRType::Value:
    740      // No need for boxing for these types.
    741      return true;
    742    default:
    743      // Any other types need to be boxed.
    744      break;
    745  }
    746 
    747  in = BoxAt(alloc, ins, in);
    748  ins->replaceOperand(0, in);
    749  return true;
    750 }
    751 
    752 bool ToStringPolicy::staticAdjustInputs(TempAllocator& alloc,
    753                                        MInstruction* ins) {
    754  MOZ_ASSERT(ins->isToString());
    755 
    756  MIRType type = ins->getOperand(0)->type();
    757  if (type == MIRType::Object || type == MIRType::Symbol ||
    758      type == MIRType::BigInt) {
    759    ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
    760    return true;
    761  }
    762 
    763  // TODO remove the following line once 966957 has landed
    764  EnsureOperandNotFloat32(alloc, ins, 0);
    765 
    766  return true;
    767 }
    768 
    769 bool ToInt64Policy::staticAdjustInputs(TempAllocator& alloc,
    770                                       MInstruction* ins) {
    771  MOZ_ASSERT(ins->isToInt64());
    772 
    773  MDefinition* input = ins->getOperand(0);
    774  MIRType type = input->type();
    775 
    776  switch (type) {
    777    case MIRType::BigInt: {
    778      auto* replace = MTruncateBigIntToInt64::New(alloc, input);
    779      ins->block()->insertBefore(ins, replace);
    780      ins->replaceOperand(0, replace);
    781      break;
    782    }
    783    // No need for boxing for these types, because they are handled specially
    784    // when this instruction is lowered to LIR.
    785    case MIRType::Boolean:
    786    case MIRType::String:
    787    case MIRType::Int64:
    788    case MIRType::Value:
    789      break;
    790    default:
    791      ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
    792      break;
    793  }
    794 
    795  return true;
    796 }
    797 
    798 template <unsigned Op>
    799 bool ObjectPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
    800                                          MInstruction* ins) {
    801  MOZ_ASSERT(ins->getOperand(Op)->type() != MIRType::Slots);
    802  MOZ_ASSERT(ins->getOperand(Op)->type() != MIRType::Elements);
    803 
    804  return UnboxOperand(alloc, ins, Op, MIRType::Object);
    805 }
    806 
    807 template bool ObjectPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
    808                                                  MInstruction* ins);
    809 template bool ObjectPolicy<1>::staticAdjustInputs(TempAllocator& alloc,
    810                                                  MInstruction* ins);
    811 template bool ObjectPolicy<2>::staticAdjustInputs(TempAllocator& alloc,
    812                                                  MInstruction* ins);
    813 template bool ObjectPolicy<3>::staticAdjustInputs(TempAllocator& alloc,
    814                                                  MInstruction* ins);
    815 
    816 bool CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
    817  MCallBase* call;
    818  if (ins->isCall()) {
    819    call = ins->toCall();
    820  } else {
    821    call = ins->toCallClassHook();
    822  }
    823 
    824  MDefinition* func = call->getCallee();
    825  if (func->type() != MIRType::Object) {
    826    MInstruction* unbox =
    827        MUnbox::New(alloc, func, MIRType::Object, MUnbox::Fallible);
    828    SetTypePolicyBailoutKind(unbox, call);
    829    call->block()->insertBefore(call, unbox);
    830    call->replaceCallee(unbox);
    831 
    832    if (!unbox->typePolicy()->adjustInputs(alloc, unbox)) {
    833      return false;
    834    }
    835  }
    836 
    837  for (uint32_t i = 0; i < call->numStackArgs(); i++) {
    838    if (!alloc.ensureBallast()) {
    839      return false;
    840    }
    841    EnsureOperandNotFloat32(alloc, call, MCallBase::IndexOfStackArg(i));
    842  }
    843 
    844  return true;
    845 }
    846 
    847 bool MegamorphicSetElementPolicy::adjustInputs(TempAllocator& alloc,
    848                                               MInstruction* ins) const {
    849  // The first operand should be an object.
    850  if (!SingleObjectPolicy::staticAdjustInputs(alloc, ins)) {
    851    return false;
    852  }
    853 
    854  // Box the index and value operands.
    855  for (size_t i = 1, e = ins->numOperands(); i < e; i++) {
    856    MDefinition* in = ins->getOperand(i);
    857    if (in->type() == MIRType::Value) {
    858      continue;
    859    }
    860    ins->replaceOperand(i, BoxAt(alloc, ins, in));
    861  }
    862  return true;
    863 }
    864 
    865 bool StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc,
    866                                                MInstruction* ins,
    867                                                Scalar::Type writeType,
    868                                                MDefinition* value,
    869                                                int valueOperand) {
    870  if (Scalar::isBigIntType(writeType)) {
    871    return ConvertOperand<MToInt64>(alloc, ins, valueOperand, MIRType::Int64);
    872  }
    873 
    874  MDefinition* curValue = value;
    875  // First, ensure the value is int32, boolean, double or Value.
    876  // The conversion is based on TypedArrayObjectTemplate::setElementTail.
    877  switch (value->type()) {
    878    case MIRType::Int32:
    879    case MIRType::Double:
    880    case MIRType::Float32:
    881    case MIRType::Boolean:
    882    case MIRType::Value:
    883      break;
    884    case MIRType::Null:
    885      value->setImplicitlyUsedUnchecked();
    886      value = MConstant::NewInt32(alloc, 0);
    887      ins->block()->insertBefore(ins, value->toInstruction());
    888      break;
    889    case MIRType::Undefined:
    890      value->setImplicitlyUsedUnchecked();
    891      value = MConstant::NewDouble(alloc, JS::GenericNaN());
    892      ins->block()->insertBefore(ins, value->toInstruction());
    893      break;
    894    case MIRType::Object:
    895    case MIRType::String:
    896    case MIRType::Symbol:
    897    case MIRType::BigInt:
    898      value = BoxAt(alloc, ins, value);
    899      break;
    900    default:
    901      MOZ_CRASH("Unexpected type");
    902  }
    903 
    904  if (value != curValue) {
    905    ins->replaceOperand(valueOperand, value);
    906    curValue = value;
    907  }
    908 
    909  MOZ_ASSERT(
    910      value->type() == MIRType::Int32 || value->type() == MIRType::Boolean ||
    911      value->type() == MIRType::Double || value->type() == MIRType::Float32 ||
    912      value->type() == MIRType::Value);
    913 
    914  switch (writeType) {
    915    case Scalar::Int8:
    916    case Scalar::Uint8:
    917    case Scalar::Int16:
    918    case Scalar::Uint16:
    919    case Scalar::Int32:
    920    case Scalar::Uint32:
    921      if (value->type() != MIRType::Int32) {
    922        value = MTruncateToInt32::New(alloc, value);
    923        ins->block()->insertBefore(ins, value->toInstruction());
    924      }
    925      break;
    926    case Scalar::Uint8Clamped:
    927      // The transpiler should have inserted MClampToUint8.
    928      MOZ_ASSERT(value->type() == MIRType::Int32);
    929      break;
    930    case Scalar::Float16:
    931      value = MToFloat16::New(alloc, value);
    932      ins->block()->insertBefore(ins, value->toInstruction());
    933      break;
    934    case Scalar::Float32:
    935      if (value->type() != MIRType::Float32) {
    936        value = MToFloat32::New(alloc, value);
    937        ins->block()->insertBefore(ins, value->toInstruction());
    938      }
    939      break;
    940    case Scalar::Float64:
    941      if (value->type() != MIRType::Double) {
    942        value = MToDouble::New(alloc, value);
    943        ins->block()->insertBefore(ins, value->toInstruction());
    944      }
    945      break;
    946    default:
    947      MOZ_CRASH("Invalid array type");
    948  }
    949 
    950  // Canonicalize floating point values for differential testing.
    951  if (Scalar::isFloatingType(writeType) && js::SupportDifferentialTesting()) {
    952    value = MCanonicalizeNaN::New(alloc, value);
    953    ins->block()->insertBefore(ins, value->toInstruction());
    954  }
    955 
    956  if (value != curValue) {
    957    ins->replaceOperand(valueOperand, value);
    958  }
    959 
    960  return true;
    961 }
    962 
    963 bool StoreUnboxedScalarPolicy::adjustInputs(TempAllocator& alloc,
    964                                            MInstruction* ins) const {
    965  MStoreUnboxedScalar* store = ins->toStoreUnboxedScalar();
    966  MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
    967  MOZ_ASSERT(store->index()->type() == MIRType::IntPtr);
    968 
    969  return adjustValueInput(alloc, store, store->writeType(), store->value(), 2);
    970 }
    971 
    972 bool StoreDataViewElementPolicy::adjustInputs(TempAllocator& alloc,
    973                                              MInstruction* ins) const {
    974  auto* store = ins->toStoreDataViewElement();
    975  MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
    976  MOZ_ASSERT(store->index()->type() == MIRType::IntPtr);
    977  MOZ_ASSERT(store->littleEndian()->type() == MIRType::Boolean);
    978 
    979  return StoreUnboxedScalarPolicy::adjustValueInput(
    980      alloc, ins, store->writeType(), store->value(), 2);
    981 }
    982 
    983 bool StoreTypedArrayHolePolicy::adjustInputs(TempAllocator& alloc,
    984                                             MInstruction* ins) const {
    985  MStoreTypedArrayElementHole* store = ins->toStoreTypedArrayElementHole();
    986  MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
    987  MOZ_ASSERT(store->index()->type() == MIRType::IntPtr);
    988  MOZ_ASSERT(store->length()->type() == MIRType::IntPtr);
    989 
    990  return StoreUnboxedScalarPolicy::adjustValueInput(
    991      alloc, ins, store->arrayType(), store->value(), 3);
    992 }
    993 
    994 bool TypedArrayFillPolicy::adjustInputs(TempAllocator& alloc,
    995                                        MInstruction* ins) const {
    996  auto* fill = ins->toTypedArrayFill();
    997  MOZ_ASSERT(fill->object()->type() == MIRType::Object);
    998  MOZ_ASSERT(fill->start()->type() == MIRType::IntPtr);
    999  MOZ_ASSERT(fill->end()->type() == MIRType::IntPtr);
   1000 
   1001  return StoreUnboxedScalarPolicy::adjustValueInput(
   1002      alloc, ins, fill->elementType(), fill->value(), 1);
   1003 }
   1004 
   1005 bool ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
   1006  MDefinition* in = ins->toClampToUint8()->input();
   1007 
   1008  switch (in->type()) {
   1009    case MIRType::Int32:
   1010    case MIRType::Double:
   1011    case MIRType::Value:
   1012      break;
   1013    default:
   1014      ins->replaceOperand(0, BoxAt(alloc, ins, in));
   1015      break;
   1016  }
   1017 
   1018  return true;
   1019 }
   1020 
   1021 // Lists of all TypePolicy specializations which are used by MIR Instructions.
   1022 #define TYPE_POLICY_LIST(_)      \
   1023  _(AllDoublePolicy)             \
   1024  _(ArithPolicy)                 \
   1025  _(BigIntArithPolicy)           \
   1026  _(BitwisePolicy)               \
   1027  _(BoxInputsPolicy)             \
   1028  _(CallPolicy)                  \
   1029  _(MegamorphicSetElementPolicy) \
   1030  _(ClampPolicy)                 \
   1031  _(ComparePolicy)               \
   1032  _(PowPolicy)                   \
   1033  _(SignPolicy)                  \
   1034  _(StoreDataViewElementPolicy)  \
   1035  _(StoreTypedArrayHolePolicy)   \
   1036  _(StoreUnboxedScalarPolicy)    \
   1037  _(TestPolicy)                  \
   1038  _(ToDoublePolicy)              \
   1039  _(ToInt32Policy)               \
   1040  _(ToBigIntPolicy)              \
   1041  _(ToStringPolicy)              \
   1042  _(ToInt64Policy)               \
   1043  _(TypedArrayFillPolicy)
   1044 
   1045 #define TEMPLATE_TYPE_POLICY_LIST(_)                                          \
   1046  _(BigIntPolicy<0>)                                                          \
   1047  _(BooleanPolicy<0>)                                                         \
   1048  _(BoxExceptPolicy<0, MIRType::Object>)                                      \
   1049  _(BoxPolicy<0>)                                                             \
   1050  _(ConvertToInt32Policy<0>)                                                  \
   1051  _(ConvertToStringPolicy<0>)                                                 \
   1052  _(ConvertToStringPolicy<2>)                                                 \
   1053  _(DoublePolicy<0>)                                                          \
   1054  _(FloatingPointPolicy<0>)                                                   \
   1055  _(UnboxedInt32Policy<0>)                                                    \
   1056  _(UnboxedInt32Policy<1>)                                                    \
   1057  _(IntPtrPolicy<0>)                                                          \
   1058  _(TruncateToInt32OrToInt64Policy<2>)                                        \
   1059  _(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, BoxPolicy<2>>)                \
   1060  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2>>)                   \
   1061  IF_EXPLICIT_RESOURCE_MANAGEMENT(                                            \
   1062      _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2>,                \
   1063                  BooleanPolicy<3>>))                                         \
   1064  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2>>)                \
   1065  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy<2>>)          \
   1066  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, BoxPolicy<2>>)          \
   1067  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>) \
   1068  _(MixPolicy<ObjectPolicy<0>, IntPtrPolicy<1>>)                              \
   1069  _(MixPolicy<ObjectPolicy<0>, IntPtrPolicy<1>, IntPtrPolicy<2>>)             \
   1070  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<2>>)                                 \
   1071  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, UnboxedInt32Policy<2>>)       \
   1072  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, IntPtrPolicy<2>>)             \
   1073  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, ObjectPolicy<2>>)             \
   1074  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, BoxPolicy<2>>)                \
   1075  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, UnboxedInt32Policy<2>,        \
   1076              BoxPolicy<3>>)                                                  \
   1077  _(MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>) \
   1078  _(MixPolicy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2>>)             \
   1079  _(MixPolicy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2>>)             \
   1080  _(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, UnboxedInt32Policy<2>>)       \
   1081  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, BoxPolicy<2>,           \
   1082              ObjectPolicy<3>>)                                               \
   1083  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>,  \
   1084              UnboxedInt32Policy<3>>)                                         \
   1085  _(MixPolicy<TruncateToInt32OrToInt64Policy<2>,                              \
   1086              TruncateToInt32OrToInt64Policy<3>>)                             \
   1087  _(MixPolicy<ObjectPolicy<0>, CacheIdPolicy<1>, NoFloatPolicy<2>>)           \
   1088  _(MixPolicy<ObjectPolicy<0>, BoxExceptPolicy<1, MIRType::Object>,           \
   1089              CacheIdPolicy<2>>)                                              \
   1090  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, IntPtrPolicy<2>,              \
   1091              IntPtrPolicy<3>, IntPtrPolicy<4>>)                              \
   1092  _(MixPolicy<BoxPolicy<0>, ObjectPolicy<1>>)                                 \
   1093  _(MixPolicy<ConvertToStringPolicy<0>, ConvertToStringPolicy<1>>)            \
   1094  _(MixPolicy<ConvertToStringPolicy<0>, ObjectPolicy<1>>)                     \
   1095  _(MixPolicy<DoublePolicy<0>, DoublePolicy<1>>)                              \
   1096  _(MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>>)                  \
   1097  _(MixPolicy<Int32OrIntPtrPolicy<0>, Int32OrIntPtrPolicy<1>>)                \
   1098  _(MixPolicy<IntPtrPolicy<0>, IntPtrPolicy<1>>)                              \
   1099  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>)                                 \
   1100  _(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, CacheIdPolicy<1>>)         \
   1101  _(MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1>>)                             \
   1102  _(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<1>>)                     \
   1103  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>>)                        \
   1104  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<2>>)                        \
   1105  _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<1>>)                             \
   1106  _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<2>>)                             \
   1107  _(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<3>>)                             \
   1108  _(MixPolicy<ObjectPolicy<0>, NoFloatPolicyAfter<1>>)                        \
   1109  _(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>>)                              \
   1110  _(MixPolicy<ObjectPolicy<0>, StringPolicy<1>>)                              \
   1111  _(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<2>>)                     \
   1112  _(MixPolicy<ObjectPolicy<1>, ConvertToStringPolicy<0>>)                     \
   1113  _(MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>>)                        \
   1114  _(MixPolicy<StringPolicy<0>, StringPolicy<1>>)                              \
   1115  _(MixPolicy<BoxPolicy<0>, BoxPolicy<1>>)                                    \
   1116  _(MixPolicy<BoxPolicy<0>, BoxPolicy<1>, BoxPolicy<2>>)                      \
   1117  _(MixPolicy<ObjectPolicy<0>, BoxPolicy<2>, ObjectPolicy<3>>)                \
   1118  _(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, ObjectPolicy<1>>)          \
   1119  _(MixPolicy<UnboxedInt32Policy<0>, BigIntPolicy<1>>)                        \
   1120  _(MixPolicy<UnboxedInt32Policy<0>, NoFloatPolicyAfter<1>>)                  \
   1121  _(MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>,                   \
   1122              NoFloatPolicyAfter<2>>)                                         \
   1123  _(MixPolicy<IntPtrPolicy<0>, IntPtrPolicy<1>, IntPtrPolicy<2>>)             \
   1124  _(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, NoFloatPolicy<2>>)      \
   1125  _(MixPolicy<UnboxedInt32Policy<1>, NoFloatPolicy<2>>)                       \
   1126  _(NoFloatPolicy<0>)                                                         \
   1127  _(NoFloatPolicy<1>)                                                         \
   1128  _(NoFloatPolicy<2>)                                                         \
   1129  _(NoFloatPolicyAfter<0>)                                                    \
   1130  _(NoFloatPolicyAfter<1>)                                                    \
   1131  _(NoFloatPolicyAfter<2>)                                                    \
   1132  _(ObjectPolicy<0>)                                                          \
   1133  _(ObjectPolicy<1>)                                                          \
   1134  _(ObjectPolicy<3>)                                                          \
   1135  _(StringPolicy<0>)                                                          \
   1136  _(SymbolPolicy<0>)
   1137 
   1138 namespace js {
   1139 namespace jit {
   1140 
   1141 // Define for all used TypePolicy specialization, the definition for
   1142 // |TypePolicy::Data::thisTypePolicy|.  This function returns one constant
   1143 // instance of the TypePolicy which is shared among all MIR Instructions of the
   1144 // same type.
   1145 //
   1146 // This Macro use __VA_ARGS__ to account for commas of template parameters.
   1147 #define DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_(...)      \
   1148  const TypePolicy* __VA_ARGS__::Data::thisTypePolicy() { \
   1149    static constexpr __VA_ARGS__ singletonType;           \
   1150    return &singletonType;                                \
   1151  }
   1152 
   1153 TYPE_POLICY_LIST(DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
   1154 TEMPLATE_TYPE_POLICY_LIST(template <> DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
   1155 #undef DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_
   1156 
   1157 }  // namespace jit
   1158 }  // namespace js
   1159 
   1160 namespace {
   1161 
   1162 // For extra-good measure in case an unqualified use is ever introduced.  (The
   1163 // main use in the macro below is explicitly qualified so as not to consult
   1164 // this scope and find this function.)
   1165 inline TypePolicy* thisTypePolicy() = delete;
   1166 
   1167 static MIRType thisTypeSpecialization() {
   1168  MOZ_CRASH("TypeSpecialization lacks definition of thisTypeSpecialization.");
   1169 }
   1170 
   1171 }  // namespace
   1172 
   1173 // For each MIR Instruction, this macro define the |typePolicy| method which is
   1174 // using the |thisTypePolicy| method.  The |thisTypePolicy| method is either a
   1175 // member of the MIR Instruction, such as with MGetElementCache, a member
   1176 // inherited from the TypePolicy::Data structure, or a member inherited from
   1177 // NoTypePolicy if the MIR instruction has no type policy.
   1178 #define DEFINE_MIR_TYPEPOLICY_MEMBERS_(op)             \
   1179  const TypePolicy* js::jit::M##op::typePolicy() {     \
   1180    return M##op::thisTypePolicy();                    \
   1181  }                                                    \
   1182                                                       \
   1183  MIRType js::jit::M##op::typePolicySpecialization() { \
   1184    return thisTypeSpecialization();                   \
   1185  }
   1186 
   1187 MIR_OPCODE_LIST(DEFINE_MIR_TYPEPOLICY_MEMBERS_)
   1188 #undef DEFINE_MIR_TYPEPOLICY_MEMBERS_