LCOV - code coverage report
Current view: top level - js/src/jit/shared - Lowering-shared-inl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 146 291 50.2 %
Date: 2017-07-14 16:53:18 Functions: 111 332 33.4 %
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             : #ifndef jit_shared_Lowering_shared_inl_h
       8             : #define jit_shared_Lowering_shared_inl_h
       9             : 
      10             : #include "jit/shared/Lowering-shared.h"
      11             : 
      12             : #include "jit/MIR.h"
      13             : #include "jit/MIRGenerator.h"
      14             : 
      15             : namespace js {
      16             : namespace jit {
      17             : 
      18             : void
      19         237 : LIRGeneratorShared::emitAtUses(MInstruction* mir)
      20             : {
      21         237 :     MOZ_ASSERT(mir->canEmitAtUses());
      22         237 :     mir->setEmittedAtUses();
      23         237 :     mir->setVirtualRegister(0);
      24         237 : }
      25             : 
      26             : LUse
      27        5866 : LIRGeneratorShared::use(MDefinition* mir, LUse policy)
      28             : {
      29             :     // It is illegal to call use() on an instruction with two defs.
      30             : #if BOX_PIECES > 1
      31             :     MOZ_ASSERT(mir->type() != MIRType::Value);
      32             : #endif
      33             : #if INT64_PIECES > 1
      34             :     MOZ_ASSERT(mir->type() != MIRType::Int64);
      35             : #endif
      36        5866 :     ensureDefined(mir);
      37        5866 :     policy.setVirtualRegister(mir->virtualRegister());
      38        5866 :     return policy;
      39             : }
      40             : 
      41             : template <size_t X> void
      42         289 : LIRGeneratorShared::define(details::LInstructionFixedDefsTempsHelper<1, X>* lir, MDefinition* mir,
      43             :                            LDefinition::Policy policy)
      44             : {
      45         289 :     LDefinition::Type type = LDefinition::TypeFrom(mir->type());
      46         289 :     define(lir, mir, LDefinition(type, policy));
      47         289 : }
      48             : 
      49             : template <size_t X> void
      50         404 : LIRGeneratorShared::define(details::LInstructionFixedDefsTempsHelper<1, X>* lir, MDefinition* mir,
      51             :                            const LDefinition& def)
      52             : {
      53             :     // Call instructions should use defineReturn.
      54         404 :     MOZ_ASSERT(!lir->isCall());
      55             : 
      56         404 :     uint32_t vreg = getVirtualRegister();
      57             : 
      58             :     // Assign the definition and a virtual register. Then, propagate this
      59             :     // virtual register to the MIR, so we can map MIR to LIR during lowering.
      60         404 :     lir->setDef(0, def);
      61         404 :     lir->getDef(0)->setVirtualRegister(vreg);
      62         404 :     lir->setMir(mir);
      63         404 :     mir->setVirtualRegister(vreg);
      64         404 :     add(lir);
      65         404 : }
      66             : 
      67             : template <size_t X, size_t Y> void
      68          15 : LIRGeneratorShared::defineFixed(LInstructionHelper<1, X, Y>* lir, MDefinition* mir,
      69             :                                 const LAllocation& output)
      70             : {
      71          15 :     LDefinition::Type type = LDefinition::TypeFrom(mir->type());
      72             : 
      73          15 :     LDefinition def(type, LDefinition::FIXED);
      74          15 :     def.setOutput(output);
      75             : 
      76          15 :     define(lir, mir, def);
      77          15 : }
      78             : 
      79             : template <size_t Ops, size_t Temps> void
      80           0 : LIRGeneratorShared::defineInt64Fixed(LInstructionHelper<INT64_PIECES, Ops, Temps>* lir, MDefinition* mir,
      81             :                                      const LInt64Allocation& output)
      82             : {
      83           0 :     uint32_t vreg = getVirtualRegister();
      84             : 
      85             : #if JS_BITS_PER_WORD == 64
      86           0 :     LDefinition def(LDefinition::GENERAL, LDefinition::FIXED);
      87           0 :     def.setOutput(output.value());
      88           0 :     lir->setDef(0, def);
      89           0 :     lir->getDef(0)->setVirtualRegister(vreg);
      90             : #else
      91             :     LDefinition def0(LDefinition::GENERAL, LDefinition::FIXED);
      92             :     def0.setOutput(output.low());
      93             :     lir->setDef(0, def0);
      94             :     lir->getDef(0)->setVirtualRegister(vreg);
      95             : 
      96             :     getVirtualRegister();
      97             :     LDefinition def1(LDefinition::GENERAL, LDefinition::FIXED);
      98             :     def1.setOutput(output.high());
      99             :     lir->setDef(1, def1);
     100             :     lir->getDef(1)->setVirtualRegister(vreg + 1);
     101             : #endif
     102             : 
     103           0 :     lir->setMir(mir);
     104           0 :     mir->setVirtualRegister(vreg);
     105           0 :     add(lir);
     106           0 : }
     107             : 
     108             : template <size_t Ops, size_t Temps> void
     109          13 : LIRGeneratorShared::defineReuseInput(LInstructionHelper<1, Ops, Temps>* lir, MDefinition* mir, uint32_t operand)
     110             : {
     111             :     // Note: Any other operand that is not the same as this operand should be
     112             :     // marked as not being "atStart". The regalloc cannot handle those and can
     113             :     // overwrite the inputs!
     114             : 
     115             :     // The input should be used at the start of the instruction, to avoid moves.
     116          13 :     MOZ_ASSERT(lir->getOperand(operand)->toUse()->usedAtStart());
     117             : 
     118          13 :     LDefinition::Type type = LDefinition::TypeFrom(mir->type());
     119             : 
     120          13 :     LDefinition def(type, LDefinition::MUST_REUSE_INPUT);
     121          13 :     def.setReusedInput(operand);
     122             : 
     123          13 :     define(lir, mir, def);
     124          13 : }
     125             : 
     126             : template <size_t Ops, size_t Temps> void
     127           0 : LIRGeneratorShared::defineInt64ReuseInput(LInstructionHelper<INT64_PIECES, Ops, Temps>* lir,
     128             :                                           MDefinition* mir, uint32_t operand)
     129             : {
     130             :     // Note: Any other operand that is not the same as this operand should be
     131             :     // marked as not being "atStart". The regalloc cannot handle those and can
     132             :     // overwrite the inputs!
     133             : 
     134             :     // The input should be used at the start of the instruction, to avoid moves.
     135           0 :     MOZ_ASSERT(lir->getOperand(operand)->toUse()->usedAtStart());
     136             : #if JS_BITS_PER_WORD == 32
     137             :     MOZ_ASSERT(lir->getOperand(operand + 1)->toUse()->usedAtStart());
     138             : #endif
     139           0 :     MOZ_ASSERT(!lir->isCall());
     140             : 
     141           0 :     uint32_t vreg = getVirtualRegister();
     142             : 
     143           0 :     LDefinition def1(LDefinition::GENERAL, LDefinition::MUST_REUSE_INPUT);
     144           0 :     def1.setReusedInput(operand);
     145           0 :     lir->setDef(0, def1);
     146           0 :     lir->getDef(0)->setVirtualRegister(vreg);
     147             : 
     148             : #if JS_BITS_PER_WORD == 32
     149             :     getVirtualRegister();
     150             :     LDefinition def2(LDefinition::GENERAL, LDefinition::MUST_REUSE_INPUT);
     151             :     def2.setReusedInput(operand + 1);
     152             :     lir->setDef(1, def2);
     153             :     lir->getDef(1)->setVirtualRegister(vreg + 1);
     154             : #endif
     155             : 
     156           0 :     lir->setMir(mir);
     157           0 :     mir->setVirtualRegister(vreg);
     158           0 :     add(lir);
     159             : 
     160           0 : }
     161             : 
     162             : template <size_t Ops, size_t Temps> void
     163         132 : LIRGeneratorShared::defineBox(LInstructionHelper<BOX_PIECES, Ops, Temps>* lir, MDefinition* mir,
     164             :                               LDefinition::Policy policy)
     165             : {
     166             :     // Call instructions should use defineReturn.
     167         132 :     MOZ_ASSERT(!lir->isCall());
     168         132 :     MOZ_ASSERT(mir->type() == MIRType::Value);
     169             : 
     170         132 :     uint32_t vreg = getVirtualRegister();
     171             : 
     172             : #if defined(JS_NUNBOX32)
     173             :     lir->setDef(0, LDefinition(vreg + VREG_TYPE_OFFSET, LDefinition::TYPE, policy));
     174             :     lir->setDef(1, LDefinition(vreg + VREG_DATA_OFFSET, LDefinition::PAYLOAD, policy));
     175             :     getVirtualRegister();
     176             : #elif defined(JS_PUNBOX64)
     177         132 :     lir->setDef(0, LDefinition(vreg, LDefinition::BOX, policy));
     178             : #endif
     179         132 :     lir->setMir(mir);
     180             : 
     181         132 :     mir->setVirtualRegister(vreg);
     182         132 :     add(lir);
     183         132 : }
     184             : 
     185             : template <size_t Ops, size_t Temps> void
     186           0 : LIRGeneratorShared::defineInt64(LInstructionHelper<INT64_PIECES, Ops, Temps>* lir, MDefinition* mir,
     187             :                                 LDefinition::Policy policy)
     188             : {
     189             :     // Call instructions should use defineReturn.
     190           0 :     MOZ_ASSERT(!lir->isCall());
     191           0 :     MOZ_ASSERT(mir->type() == MIRType::Int64);
     192             : 
     193           0 :     uint32_t vreg = getVirtualRegister();
     194             : 
     195             : #if JS_BITS_PER_WORD == 32
     196             :     lir->setDef(0, LDefinition(vreg + INT64LOW_INDEX, LDefinition::GENERAL, policy));
     197             :     lir->setDef(1, LDefinition(vreg + INT64HIGH_INDEX, LDefinition::GENERAL, policy));
     198             :     getVirtualRegister();
     199             : #else
     200           0 :     lir->setDef(0, LDefinition(vreg, LDefinition::GENERAL, policy));
     201             : #endif
     202           0 :     lir->setMir(mir);
     203             : 
     204           0 :     mir->setVirtualRegister(vreg);
     205           0 :     add(lir);
     206           0 : }
     207             : 
     208             : void
     209           0 : LIRGeneratorShared::defineSharedStubReturn(LInstruction* lir, MDefinition* mir)
     210             : {
     211           0 :     lir->setMir(mir);
     212             : 
     213           0 :     MOZ_ASSERT(lir->isBinarySharedStub() || lir->isUnarySharedStub() || lir->isNullarySharedStub());
     214           0 :     MOZ_ASSERT(mir->type() == MIRType::Value);
     215             : 
     216           0 :     uint32_t vreg = getVirtualRegister();
     217             : 
     218             : #if defined(JS_NUNBOX32)
     219             :     lir->setDef(TYPE_INDEX, LDefinition(vreg + VREG_TYPE_OFFSET, LDefinition::TYPE,
     220             :                                         LGeneralReg(JSReturnReg_Type)));
     221             :     lir->setDef(PAYLOAD_INDEX, LDefinition(vreg + VREG_DATA_OFFSET, LDefinition::PAYLOAD,
     222             :                                            LGeneralReg(JSReturnReg_Data)));
     223             :     getVirtualRegister();
     224             : #elif defined(JS_PUNBOX64)
     225           0 :     lir->setDef(0, LDefinition(vreg, LDefinition::BOX, LGeneralReg(JSReturnReg)));
     226             : #endif
     227             : 
     228           0 :     mir->setVirtualRegister(vreg);
     229           0 :     add(lir);
     230           0 : }
     231             : 
     232             : void
     233          37 : LIRGeneratorShared::defineReturn(LInstruction* lir, MDefinition* mir)
     234             : {
     235          37 :     lir->setMir(mir);
     236             : 
     237          37 :     MOZ_ASSERT(lir->isCall());
     238          37 :     gen->setNeedsStaticStackAlignment();
     239             : 
     240          37 :     uint32_t vreg = getVirtualRegister();
     241             : 
     242          37 :     switch (mir->type()) {
     243             :       case MIRType::Value:
     244             : #if defined(JS_NUNBOX32)
     245             :         lir->setDef(TYPE_INDEX, LDefinition(vreg + VREG_TYPE_OFFSET, LDefinition::TYPE,
     246             :                                             LGeneralReg(JSReturnReg_Type)));
     247             :         lir->setDef(PAYLOAD_INDEX, LDefinition(vreg + VREG_DATA_OFFSET, LDefinition::PAYLOAD,
     248             :                                                LGeneralReg(JSReturnReg_Data)));
     249             :         getVirtualRegister();
     250             : #elif defined(JS_PUNBOX64)
     251          35 :         lir->setDef(0, LDefinition(vreg, LDefinition::BOX, LGeneralReg(JSReturnReg)));
     252             : #endif
     253          35 :         break;
     254             :       case MIRType::Int64:
     255             : #if defined(JS_NUNBOX32)
     256             :         lir->setDef(INT64LOW_INDEX, LDefinition(vreg + INT64LOW_INDEX, LDefinition::GENERAL,
     257             :                                                 LGeneralReg(ReturnReg64.low)));
     258             :         lir->setDef(INT64HIGH_INDEX, LDefinition(vreg + INT64HIGH_INDEX, LDefinition::GENERAL,
     259             :                                                  LGeneralReg(ReturnReg64.high)));
     260             :         getVirtualRegister();
     261             : #elif defined(JS_PUNBOX64)
     262           0 :         lir->setDef(0, LDefinition(vreg, LDefinition::GENERAL, LGeneralReg(ReturnReg)));
     263             : #endif
     264           0 :         break;
     265             :       case MIRType::Float32:
     266           0 :         lir->setDef(0, LDefinition(vreg, LDefinition::FLOAT32, LFloatReg(ReturnFloat32Reg)));
     267           0 :         break;
     268             :       case MIRType::Double:
     269           0 :         lir->setDef(0, LDefinition(vreg, LDefinition::DOUBLE, LFloatReg(ReturnDoubleReg)));
     270           0 :         break;
     271             :       case MIRType::Int8x16:
     272             :       case MIRType::Int16x8:
     273             :       case MIRType::Int32x4:
     274             :       case MIRType::Bool8x16:
     275             :       case MIRType::Bool16x8:
     276             :       case MIRType::Bool32x4:
     277           0 :         lir->setDef(0, LDefinition(vreg, LDefinition::SIMD128INT, LFloatReg(ReturnSimd128Reg)));
     278           0 :         break;
     279             :       case MIRType::Float32x4:
     280           0 :         lir->setDef(0, LDefinition(vreg, LDefinition::SIMD128FLOAT, LFloatReg(ReturnSimd128Reg)));
     281           0 :         break;
     282             :       default:
     283           2 :         LDefinition::Type type = LDefinition::TypeFrom(mir->type());
     284           2 :         MOZ_ASSERT(type != LDefinition::DOUBLE && type != LDefinition::FLOAT32);
     285           2 :         lir->setDef(0, LDefinition(vreg, type, LGeneralReg(ReturnReg)));
     286           2 :         break;
     287             :     }
     288             : 
     289          37 :     mir->setVirtualRegister(vreg);
     290          37 :     add(lir);
     291          37 : }
     292             : 
     293             : template <size_t Ops, size_t Temps> void
     294           0 : LIRGeneratorShared::defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefinition *mir,
     295             :                                  LDefinition::Policy policy)
     296             : {
     297           0 :     MOZ_ASSERT(lir->isCall());
     298             : 
     299           0 :     uint32_t vreg = getVirtualRegister();
     300           0 :     lir->setDef(0, LDefinition(vreg, LDefinition::DOUBLE, LFloatReg(ReturnDoubleReg)));
     301             : #if defined(JS_CODEGEN_ARM)
     302             :     lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE,
     303             :                 LFloatReg(FloatRegister(FloatRegisters::d1, FloatRegister::Double))));
     304             : #elif defined(JS_CODEGEN_ARM64)
     305             :     lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE,
     306             :                 LFloatReg(FloatRegister(FloatRegisters::d1, FloatRegisters::Double))));
     307             : #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     308             :     lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(f2)));
     309             : #elif defined(JS_CODEGEN_NONE)
     310             :     MOZ_CRASH();
     311             : #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
     312           0 :     lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(xmm1)));
     313             : #else
     314             : #error "Unsupported architecture for SinCos"
     315             : #endif
     316             : 
     317           0 :     getVirtualRegister();
     318             : 
     319           0 :     lir->setMir(mir);
     320           0 :     mir->setVirtualRegister(vreg);
     321           0 :     add(lir);
     322             : 
     323           0 :     return;
     324             : }
     325             : 
     326             : // In LIR, we treat booleans and integers as the same low-level type (INTEGER).
     327             : // When snapshotting, we recover the actual JS type from MIR. This function
     328             : // checks that when making redefinitions, we don't accidentally coerce two
     329             : // incompatible types.
     330             : static inline bool
     331         153 : IsCompatibleLIRCoercion(MIRType to, MIRType from)
     332             : {
     333         153 :     if (to == from)
     334         153 :         return true;
     335           0 :     if ((to == MIRType::Int32 || to == MIRType::Boolean) &&
     336           0 :         (from == MIRType::Int32 || from == MIRType::Boolean)) {
     337           0 :         return true;
     338             :     }
     339             :     // SIMD types can be coerced with from*Bits operators.
     340           0 :     if (IsSimdType(to) && IsSimdType(from))
     341           0 :         return true;
     342           0 :     return false;
     343             : }
     344             : 
     345             : 
     346             : // We can redefine the sin(x) and cos(x) function to return the sincos result.
     347             : void
     348           0 : LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as, MMathFunction::Function func)
     349             : {
     350           0 :     MOZ_ASSERT(def->isMathFunction());
     351           0 :     MOZ_ASSERT(def->type() == MIRType::Double && as->type() == MIRType::SinCosDouble);
     352           0 :     MOZ_ASSERT(MMathFunction::Sin == func || MMathFunction::Cos == func);
     353             : 
     354           0 :     ensureDefined(as);
     355           0 :     MMathFunction *math = def->toMathFunction();
     356             : 
     357           0 :     MOZ_ASSERT(math->function() == MMathFunction::Cos ||
     358             :                math->function() == MMathFunction::Sin);
     359             : 
     360             :     // The sincos returns two values:
     361             :     // - VREG: it returns the sin's value of the sincos;
     362             :     // - VREG + VREG_INCREMENT: it returns the cos' value of the sincos.
     363           0 :     if (math->function() == MMathFunction::Sin)
     364           0 :         def->setVirtualRegister(as->virtualRegister());
     365             :     else
     366           0 :         def->setVirtualRegister(as->virtualRegister() + VREG_INCREMENT);
     367           0 : }
     368             : 
     369             : void
     370         153 : LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as)
     371             : {
     372         153 :     MOZ_ASSERT(IsCompatibleLIRCoercion(def->type(), as->type()));
     373             : 
     374             :     // Try to emit MIR marked as emitted-at-uses at, well, uses. For
     375             :     // snapshotting reasons we delay the MIRTypes match, or when we are
     376             :     // coercing between bool and int32 constants.
     377         153 :     if (as->isEmittedAtUses() &&
     378           0 :         (def->type() == as->type() ||
     379           0 :          (as->isConstant() &&
     380           0 :           (def->type() == MIRType::Int32 || def->type() == MIRType::Boolean) &&
     381           0 :           (as->type() == MIRType::Int32 || as->type() == MIRType::Boolean))))
     382             :     {
     383             :         MInstruction* replacement;
     384           0 :         if (def->type() != as->type()) {
     385           0 :             if (as->type() == MIRType::Int32)
     386           0 :                 replacement = MConstant::New(alloc(), BooleanValue(as->toConstant()->toInt32()));
     387             :             else
     388           0 :                 replacement = MConstant::New(alloc(), Int32Value(as->toConstant()->toBoolean()));
     389           0 :             def->block()->insertBefore(def->toInstruction(), replacement);
     390           0 :             emitAtUses(replacement->toInstruction());
     391             :         } else {
     392           0 :             replacement = as->toInstruction();
     393             :         }
     394           0 :         def->replaceAllUsesWith(replacement);
     395             :     } else {
     396         153 :         ensureDefined(as);
     397         153 :         def->setVirtualRegister(as->virtualRegister());
     398             : 
     399             : #ifdef DEBUG
     400         306 :         if (JitOptions.runExtraChecks &&
     401         153 :             def->resultTypeSet() && as->resultTypeSet() &&
     402           0 :             !def->resultTypeSet()->equals(as->resultTypeSet()))
     403             :         {
     404           0 :             switch (def->type()) {
     405             :               case MIRType::Object:
     406             :               case MIRType::ObjectOrNull:
     407             :               case MIRType::String:
     408             :               case MIRType::Symbol: {
     409           0 :                 LAssertResultT* check = new(alloc()) LAssertResultT(useRegister(def));
     410           0 :                 add(check, def->toInstruction());
     411           0 :                 break;
     412             :               }
     413             :               case MIRType::Value: {
     414           0 :                 LAssertResultV* check = new(alloc()) LAssertResultV(useBox(def));
     415           0 :                 add(check, def->toInstruction());
     416           0 :                 break;
     417             :               }
     418             :               default:
     419           0 :                 break;
     420             :             }
     421             :         }
     422             : #endif
     423             :     }
     424         153 : }
     425             : 
     426             : void
     427        6554 : LIRGeneratorShared::ensureDefined(MDefinition* mir)
     428             : {
     429        6554 :     if (mir->isEmittedAtUses()) {
     430         118 :         mir->toInstruction()->accept(this);
     431         118 :         MOZ_ASSERT(mir->isLowered());
     432             :     }
     433        6554 : }
     434             : 
     435             : LUse
     436         387 : LIRGeneratorShared::useRegister(MDefinition* mir)
     437             : {
     438         387 :     return use(mir, LUse(LUse::REGISTER));
     439             : }
     440             : 
     441             : LUse
     442         177 : LIRGeneratorShared::useRegisterAtStart(MDefinition* mir)
     443             : {
     444         177 :     return use(mir, LUse(LUse::REGISTER, true));
     445             : }
     446             : 
     447             : LUse
     448           9 : LIRGeneratorShared::use(MDefinition* mir)
     449             : {
     450           9 :     return use(mir, LUse(LUse::ANY));
     451             : }
     452             : 
     453             : LUse
     454          29 : LIRGeneratorShared::useAtStart(MDefinition* mir)
     455             : {
     456          29 :     return use(mir, LUse(LUse::ANY, true));
     457             : }
     458             : 
     459             : LAllocation
     460          54 : LIRGeneratorShared::useOrConstant(MDefinition* mir)
     461             : {
     462          54 :     if (mir->isConstant())
     463          45 :         return LAllocation(mir->toConstant());
     464           9 :     return use(mir);
     465             : }
     466             : 
     467             : LAllocation
     468           0 : LIRGeneratorShared::useOrConstantAtStart(MDefinition* mir)
     469             : {
     470           0 :     if (mir->isConstant())
     471           0 :         return LAllocation(mir->toConstant());
     472           0 :     return useAtStart(mir);
     473             : }
     474             : 
     475             : LAllocation
     476         110 : LIRGeneratorShared::useRegisterOrConstant(MDefinition* mir)
     477             : {
     478         110 :     if (mir->isConstant())
     479          54 :         return LAllocation(mir->toConstant());
     480          56 :     return useRegister(mir);
     481             : }
     482             : 
     483             : LAllocation
     484           8 : LIRGeneratorShared::useRegisterOrConstantAtStart(MDefinition* mir)
     485             : {
     486           8 :     if (mir->isConstant())
     487           0 :         return LAllocation(mir->toConstant());
     488           8 :     return useRegisterAtStart(mir);
     489             : }
     490             : 
     491             : LAllocation
     492             : LIRGeneratorShared::useRegisterOrZero(MDefinition* mir)
     493             : {
     494             :     if (mir->isConstant() && mir->toConstant()->isInt32(0))
     495             :         return LAllocation();
     496             :     return useRegister(mir);
     497             : }
     498             : 
     499             : LAllocation
     500           0 : LIRGeneratorShared::useRegisterOrZeroAtStart(MDefinition* mir)
     501             : {
     502           0 :     if (mir->isConstant() && mir->toConstant()->isInt32(0))
     503           0 :         return LAllocation();
     504           0 :     return useRegisterAtStart(mir);
     505             : }
     506             : 
     507             : LAllocation
     508           6 : LIRGeneratorShared::useRegisterOrNonDoubleConstant(MDefinition* mir)
     509             : {
     510           6 :     if (mir->isConstant() && mir->type() != MIRType::Double && mir->type() != MIRType::Float32)
     511           0 :         return LAllocation(mir->toConstant());
     512           6 :     return useRegister(mir);
     513             : }
     514             : 
     515             : #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
     516             : LAllocation
     517             : LIRGeneratorShared::useAnyOrConstant(MDefinition* mir)
     518             : {
     519             :     return useRegisterOrConstant(mir);
     520             : }
     521             : LAllocation
     522             : LIRGeneratorShared::useStorable(MDefinition* mir)
     523             : {
     524             :     return useRegister(mir);
     525             : }
     526             : LAllocation
     527             : LIRGeneratorShared::useStorableAtStart(MDefinition* mir)
     528             : {
     529             :     return useRegisterAtStart(mir);
     530             : }
     531             : 
     532             : LAllocation
     533             : LIRGeneratorShared::useAny(MDefinition* mir)
     534             : {
     535             :     return useRegister(mir);
     536             : }
     537             : #else
     538             : LAllocation
     539          46 : LIRGeneratorShared::useAnyOrConstant(MDefinition* mir)
     540             : {
     541          46 :     return useOrConstant(mir);
     542             : }
     543             : 
     544             : LAllocation
     545           0 : LIRGeneratorShared::useAny(MDefinition* mir)
     546             : {
     547           0 :     return use(mir);
     548             : }
     549             : LAllocation
     550             : LIRGeneratorShared::useStorable(MDefinition* mir)
     551             : {
     552             :     return useRegisterOrConstant(mir);
     553             : }
     554             : LAllocation
     555             : LIRGeneratorShared::useStorableAtStart(MDefinition* mir)
     556             : {
     557             :     return useRegisterOrConstantAtStart(mir);
     558             : }
     559             : 
     560             : #endif
     561             : 
     562             : LAllocation
     563        5204 : LIRGeneratorShared::useKeepalive(MDefinition* mir)
     564             : {
     565        5204 :     return use(mir, LUse(LUse::KEEPALIVE));
     566             : }
     567             : 
     568             : LAllocation
     569        7013 : LIRGeneratorShared::useKeepaliveOrConstant(MDefinition* mir)
     570             : {
     571        7013 :     if (mir->isConstant())
     572        1811 :         return LAllocation(mir->toConstant());
     573        5202 :     return useKeepalive(mir);
     574             : }
     575             : 
     576             : LUse
     577          17 : LIRGeneratorShared::useFixed(MDefinition* mir, Register reg)
     578             : {
     579          17 :     return use(mir, LUse(reg));
     580             : }
     581             : 
     582             : LUse
     583          43 : LIRGeneratorShared::useFixedAtStart(MDefinition* mir, Register reg)
     584             : {
     585          43 :     return use(mir, LUse(reg, true));
     586             : }
     587             : 
     588             : LUse
     589           0 : LIRGeneratorShared::useFixed(MDefinition* mir, FloatRegister reg)
     590             : {
     591           0 :     return use(mir, LUse(reg));
     592             : }
     593             : 
     594             : LUse
     595             : LIRGeneratorShared::useFixed(MDefinition* mir, AnyRegister reg)
     596             : {
     597             :     return reg.isFloat() ? use(mir, LUse(reg.fpu())) : use(mir, LUse(reg.gpr()));
     598             : }
     599             : 
     600             : LUse
     601           0 : LIRGeneratorShared::useFixedAtStart(MDefinition* mir, AnyRegister reg)
     602             : {
     603           0 :     return reg.isFloat() ? use(mir, LUse(reg.fpu(), true)) : use(mir, LUse(reg.gpr(), true));
     604             : }
     605             : 
     606             : LDefinition
     607         314 : LIRGeneratorShared::temp(LDefinition::Type type, LDefinition::Policy policy)
     608             : {
     609         314 :     return LDefinition(getVirtualRegister(), type, policy);
     610             : }
     611             : 
     612             : LInt64Definition
     613             : LIRGeneratorShared::tempInt64(LDefinition::Policy policy)
     614             : {
     615             : #if JS_BITS_PER_WORD == 32
     616             :     LDefinition high = temp(LDefinition::GENERAL, policy);
     617             :     LDefinition low = temp(LDefinition::GENERAL, policy);
     618             :     return LInt64Definition(high, low);
     619             : #else
     620             :     return LInt64Definition(temp(LDefinition::GENERAL, policy));
     621             : #endif
     622             : }
     623             : 
     624             : LDefinition
     625         126 : LIRGeneratorShared::tempFixed(Register reg)
     626             : {
     627         126 :     LDefinition t = temp(LDefinition::GENERAL);
     628         126 :     t.setOutput(LGeneralReg(reg));
     629         126 :     return t;
     630             : }
     631             : 
     632             : LDefinition
     633           0 : LIRGeneratorShared::tempFloat32()
     634             : {
     635           0 :     return temp(LDefinition::FLOAT32);
     636             : }
     637             : 
     638             : LDefinition
     639          40 : LIRGeneratorShared::tempDouble()
     640             : {
     641          40 :     return temp(LDefinition::DOUBLE);
     642             : }
     643             : 
     644             : LDefinition
     645           0 : LIRGeneratorShared::tempCopy(MDefinition* input, uint32_t reusedInput)
     646             : {
     647           0 :     MOZ_ASSERT(input->virtualRegister());
     648           0 :     LDefinition t = temp(LDefinition::TypeFrom(input->type()), LDefinition::MUST_REUSE_INPUT);
     649           0 :     t.setReusedInput(reusedInput);
     650           0 :     return t;
     651             : }
     652             : 
     653             : template <typename T> void
     654        1534 : LIRGeneratorShared::annotate(T* ins)
     655             : {
     656        1534 :     ins->setId(lirGraph_.getInstructionId());
     657        1534 : }
     658             : 
     659             : template <typename T> void
     660        1359 : LIRGeneratorShared::add(T* ins, MInstruction* mir)
     661             : {
     662        1359 :     MOZ_ASSERT(!ins->isPhi());
     663        1359 :     current->add(ins);
     664        1359 :     if (mir) {
     665         242 :         MOZ_ASSERT(current == mir->block()->lir());
     666         242 :         ins->setMir(mir);
     667             :     }
     668        1359 :     annotate(ins);
     669        1359 : }
     670             : 
     671             : #ifdef JS_NUNBOX32
     672             : // Returns the virtual register of a js::Value-defining instruction. This is
     673             : // abstracted because MBox is a special value-returning instruction that
     674             : // redefines its input payload if its input is not constant. Therefore, it is
     675             : // illegal to request a box's payload by adding VREG_DATA_OFFSET to its raw id.
     676             : static inline uint32_t
     677             : VirtualRegisterOfPayload(MDefinition* mir)
     678             : {
     679             :     if (mir->isBox()) {
     680             :         MDefinition* inner = mir->toBox()->getOperand(0);
     681             :         if (!inner->isConstant() && inner->type() != MIRType::Double && inner->type() != MIRType::Float32)
     682             :             return inner->virtualRegister();
     683             :     }
     684             :     if (mir->isTypeBarrier())
     685             :         return VirtualRegisterOfPayload(mir->getOperand(0));
     686             :     return mir->virtualRegister() + VREG_DATA_OFFSET;
     687             : }
     688             : 
     689             : // Note: always call ensureDefined before calling useType/usePayload,
     690             : // so that emitted-at-use operands are handled correctly.
     691             : LUse
     692             : LIRGeneratorShared::useType(MDefinition* mir, LUse::Policy policy)
     693             : {
     694             :     MOZ_ASSERT(mir->type() == MIRType::Value);
     695             : 
     696             :     return LUse(mir->virtualRegister() + VREG_TYPE_OFFSET, policy);
     697             : }
     698             : 
     699             : LUse
     700             : LIRGeneratorShared::usePayload(MDefinition* mir, LUse::Policy policy)
     701             : {
     702             :     MOZ_ASSERT(mir->type() == MIRType::Value);
     703             : 
     704             :     return LUse(VirtualRegisterOfPayload(mir), policy);
     705             : }
     706             : 
     707             : LUse
     708             : LIRGeneratorShared::usePayloadAtStart(MDefinition* mir, LUse::Policy policy)
     709             : {
     710             :     MOZ_ASSERT(mir->type() == MIRType::Value);
     711             : 
     712             :     return LUse(VirtualRegisterOfPayload(mir), policy, true);
     713             : }
     714             : 
     715             : LUse
     716             : LIRGeneratorShared::usePayloadInRegisterAtStart(MDefinition* mir)
     717             : {
     718             :     return usePayloadAtStart(mir, LUse::REGISTER);
     719             : }
     720             : 
     721             : void
     722             : LIRGeneratorShared::fillBoxUses(LInstruction* lir, size_t n, MDefinition* mir)
     723             : {
     724             :     ensureDefined(mir);
     725             :     lir->getOperand(n)->toUse()->setVirtualRegister(mir->virtualRegister() + VREG_TYPE_OFFSET);
     726             :     lir->getOperand(n + 1)->toUse()->setVirtualRegister(VirtualRegisterOfPayload(mir));
     727             : }
     728             : #endif
     729             : 
     730             : LUse
     731          12 : LIRGeneratorShared::useRegisterForTypedLoad(MDefinition* mir, MIRType type)
     732             : {
     733          12 :     MOZ_ASSERT(type != MIRType::Value && type != MIRType::None);
     734          12 :     MOZ_ASSERT(mir->type() == MIRType::Object || mir->type() == MIRType::Slots);
     735             : 
     736             : #ifdef JS_PUNBOX64
     737             :     // On x64, masm.loadUnboxedValue emits slightly less efficient code when
     738             :     // the input and output use the same register and we're not loading an
     739             :     // int32/bool/double, so we just call useRegister in this case.
     740          12 :     if (type != MIRType::Int32 && type != MIRType::Boolean && type != MIRType::Double)
     741           7 :         return useRegister(mir);
     742             : #endif
     743             : 
     744           5 :     return useRegisterAtStart(mir);
     745             : }
     746             : 
     747             : LBoxAllocation
     748         105 : LIRGeneratorShared::useBox(MDefinition* mir, LUse::Policy policy, bool useAtStart)
     749             : {
     750         105 :     MOZ_ASSERT(mir->type() == MIRType::Value);
     751             : 
     752         105 :     ensureDefined(mir);
     753             : 
     754             : #if defined(JS_NUNBOX32)
     755             :     return LBoxAllocation(LUse(mir->virtualRegister(), policy, useAtStart),
     756             :                           LUse(VirtualRegisterOfPayload(mir), policy, useAtStart));
     757             : #else
     758         105 :     return LBoxAllocation(LUse(mir->virtualRegister(), policy, useAtStart));
     759             : #endif
     760             : }
     761             : 
     762             : LBoxAllocation
     763          41 : LIRGeneratorShared::useBoxOrTyped(MDefinition* mir)
     764             : {
     765          41 :     if (mir->type() == MIRType::Value)
     766           5 :         return useBox(mir);
     767             : 
     768             : 
     769             : #if defined(JS_NUNBOX32)
     770             :     return LBoxAllocation(useRegister(mir), LAllocation());
     771             : #else
     772          36 :     return LBoxAllocation(useRegister(mir));
     773             : #endif
     774             : }
     775             : 
     776             : LBoxAllocation
     777          35 : LIRGeneratorShared::useBoxOrTypedOrConstant(MDefinition* mir, bool useConstant)
     778             : {
     779          35 :     if (useConstant && mir->isConstant()) {
     780             : #if defined(JS_NUNBOX32)
     781             :         return LBoxAllocation(LAllocation(mir->toConstant()), LAllocation());
     782             : #else
     783          19 :         return LBoxAllocation(LAllocation(mir->toConstant()));
     784             : #endif
     785             :     }
     786             : 
     787          16 :     return useBoxOrTyped(mir);
     788             : }
     789             : 
     790             : LInt64Allocation
     791           0 : LIRGeneratorShared::useInt64(MDefinition* mir, LUse::Policy policy, bool useAtStart)
     792             : {
     793           0 :     MOZ_ASSERT(mir->type() == MIRType::Int64);
     794             : 
     795           0 :     ensureDefined(mir);
     796             : 
     797           0 :     uint32_t vreg = mir->virtualRegister();
     798             : #if JS_BITS_PER_WORD == 32
     799             :     return LInt64Allocation(LUse(vreg + INT64HIGH_INDEX, policy, useAtStart),
     800             :                             LUse(vreg + INT64LOW_INDEX, policy, useAtStart));
     801             : #else
     802           0 :     return LInt64Allocation(LUse(vreg, policy, useAtStart));
     803             : #endif
     804             : }
     805             : 
     806             : LInt64Allocation
     807           0 : LIRGeneratorShared::useInt64Fixed(MDefinition* mir, Register64 regs, bool useAtStart)
     808             : {
     809           0 :     MOZ_ASSERT(mir->type() == MIRType::Int64);
     810             : 
     811           0 :     ensureDefined(mir);
     812             : 
     813           0 :     uint32_t vreg = mir->virtualRegister();
     814             : #if JS_BITS_PER_WORD == 32
     815             :     return LInt64Allocation(LUse(regs.high, vreg + INT64HIGH_INDEX, useAtStart),
     816             :                             LUse(regs.low, vreg + INT64LOW_INDEX, useAtStart));
     817             : #else
     818           0 :     return LInt64Allocation(LUse(regs.reg, vreg, useAtStart));
     819             : #endif
     820             : }
     821             : 
     822             : LInt64Allocation
     823             : LIRGeneratorShared::useInt64FixedAtStart(MDefinition* mir, Register64 regs)
     824             : {
     825             :     return useInt64Fixed(mir, regs, true);
     826             : }
     827             : 
     828             : LInt64Allocation
     829           0 : LIRGeneratorShared::useInt64(MDefinition* mir, bool useAtStart)
     830             : {
     831             :     // On 32-bit platforms, always load the value in registers.
     832             : #if JS_BITS_PER_WORD == 32
     833             :     return useInt64(mir, LUse::REGISTER, useAtStart);
     834             : #else
     835           0 :     return useInt64(mir, LUse::ANY, useAtStart);
     836             : #endif
     837             : }
     838             : 
     839             : LInt64Allocation
     840           0 : LIRGeneratorShared::useInt64AtStart(MDefinition* mir)
     841             : {
     842           0 :     return useInt64(mir, /* useAtStart = */ true);
     843             : }
     844             : 
     845             : LInt64Allocation
     846           0 : LIRGeneratorShared::useInt64Register(MDefinition* mir, bool useAtStart)
     847             : {
     848           0 :     return useInt64(mir, LUse::REGISTER, useAtStart);
     849             : }
     850             : 
     851             : LInt64Allocation
     852           0 : LIRGeneratorShared::useInt64OrConstant(MDefinition* mir, bool useAtStart)
     853             : {
     854           0 :     if (mir->isConstant()) {
     855             : #if defined(JS_NUNBOX32)
     856             :         return LInt64Allocation(LAllocation(mir->toConstant()), LAllocation());
     857             : #else
     858           0 :         return LInt64Allocation(LAllocation(mir->toConstant()));
     859             : #endif
     860             :     }
     861           0 :     return useInt64(mir, useAtStart);
     862             : }
     863             : 
     864             : LInt64Allocation
     865           0 : LIRGeneratorShared::useInt64RegisterOrConstant(MDefinition* mir, bool useAtStart)
     866             : {
     867           0 :     if (mir->isConstant()) {
     868             : #if defined(JS_NUNBOX32)
     869             :         return LInt64Allocation(LAllocation(mir->toConstant()), LAllocation());
     870             : #else
     871           0 :         return LInt64Allocation(LAllocation(mir->toConstant()));
     872             : #endif
     873             :     }
     874           0 :     return useInt64Register(mir, useAtStart);
     875             : }
     876             : 
     877             : } // namespace jit
     878             : } // namespace js
     879             : 
     880             : #endif /* jit_shared_Lowering_shared_inl_h */

Generated by: LCOV version 1.13