LCOV - code coverage report
Current view: top level - js/src/jit/shared - CodeGenerator-shared-inl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 90 152 59.2 %
Date: 2017-07-14 16:53:18 Functions: 24 36 66.7 %
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_CodeGenerator_shared_inl_h
       8             : #define jit_shared_CodeGenerator_shared_inl_h
       9             : 
      10             : #include "jit/shared/CodeGenerator-shared.h"
      11             : #include "jit/Disassembler.h"
      12             : 
      13             : #include "jit/MacroAssembler-inl.h"
      14             : 
      15             : namespace js {
      16             : namespace jit {
      17             : 
      18             : static inline bool
      19           0 : IsConstant(const LInt64Allocation& a)
      20             : {
      21             : #if JS_BITS_PER_WORD == 32
      22             :     if (a.high().isConstantValue())
      23             :         return true;
      24             :     if (a.high().isConstantIndex())
      25             :         return true;
      26             : #else
      27           0 :     if (a.value().isConstantValue())
      28           0 :         return true;
      29           0 :     if (a.value().isConstantIndex())
      30           0 :         return true;
      31             : #endif
      32           0 :     return false;
      33             : }
      34             : 
      35             : static inline int32_t
      36          64 : ToInt32(const LAllocation* a)
      37             : {
      38          64 :     if (a->isConstantValue())
      39          64 :         return a->toConstant()->toInt32();
      40           0 :     if (a->isConstantIndex())
      41           0 :         return a->toConstantIndex()->index();
      42           0 :     MOZ_CRASH("this is not a constant!");
      43             : }
      44             : 
      45             : static inline int64_t
      46             : ToInt64(const LAllocation* a)
      47             : {
      48             :     if (a->isConstantValue())
      49             :         return a->toConstant()->toInt64();
      50             :     if (a->isConstantIndex())
      51             :         return a->toConstantIndex()->index();
      52             :     MOZ_CRASH("this is not a constant!");
      53             : }
      54             : 
      55             : static inline int64_t
      56           0 : ToInt64(const LInt64Allocation& a)
      57             : {
      58             : #if JS_BITS_PER_WORD == 32
      59             :     if (a.high().isConstantValue())
      60             :         return a.high().toConstant()->toInt64();
      61             :     if (a.high().isConstantIndex())
      62             :         return a.high().toConstantIndex()->index();
      63             : #else
      64           0 :     if (a.value().isConstantValue())
      65           0 :         return a.value().toConstant()->toInt64();
      66           0 :     if (a.value().isConstantIndex())
      67           0 :         return a.value().toConstantIndex()->index();
      68             : #endif
      69           0 :     MOZ_CRASH("this is not a constant!");
      70             : }
      71             : 
      72             : static inline double
      73             : ToDouble(const LAllocation* a)
      74             : {
      75             :     return a->toConstant()->numberToDouble();
      76             : }
      77             : 
      78             : static inline Register
      79        3185 : ToRegister(const LAllocation& a)
      80             : {
      81        3185 :     MOZ_ASSERT(a.isGeneralReg());
      82        3185 :     return a.toGeneralReg()->reg();
      83             : }
      84             : 
      85             : static inline Register
      86        1455 : ToRegister(const LAllocation* a)
      87             : {
      88        1455 :     return ToRegister(*a);
      89             : }
      90             : 
      91             : static inline Register
      92        1090 : ToRegister(const LDefinition* def)
      93             : {
      94        1090 :     return ToRegister(*def->output());
      95             : }
      96             : 
      97             : static inline Register64
      98           0 : ToOutRegister64(LInstruction* ins)
      99             : {
     100             : #if JS_BITS_PER_WORD == 32
     101             :     Register loReg = ToRegister(ins->getDef(INT64LOW_INDEX));
     102             :     Register hiReg = ToRegister(ins->getDef(INT64HIGH_INDEX));
     103             :     return Register64(hiReg, loReg);
     104             : #else
     105           0 :     return Register64(ToRegister(ins->getDef(0)));
     106             : #endif
     107             : }
     108             : 
     109             : static inline Register64
     110           0 : ToRegister64(const LInt64Allocation& a)
     111             : {
     112             : #if JS_BITS_PER_WORD == 32
     113             :     return Register64(ToRegister(a.high()), ToRegister(a.low()));
     114             : #else
     115           0 :     return Register64(ToRegister(a.value()));
     116             : #endif
     117             : }
     118             : 
     119             : static inline Register
     120          70 : ToTempRegisterOrInvalid(const LDefinition* def)
     121             : {
     122          70 :     if (def->isBogusTemp())
     123           0 :         return InvalidReg;
     124          70 :     return ToRegister(def);
     125             : }
     126             : 
     127             : static inline Register
     128           0 : ToTempUnboxRegister(const LDefinition* def)
     129             : {
     130           0 :     return ToTempRegisterOrInvalid(def);
     131             : }
     132             : 
     133             : static inline Register
     134           0 : ToRegisterOrInvalid(const LDefinition* a)
     135             : {
     136           0 :     return a ? ToRegister(a) : InvalidReg;
     137             : }
     138             : 
     139             : static inline FloatRegister
     140          49 : ToFloatRegister(const LAllocation& a)
     141             : {
     142          49 :     MOZ_ASSERT(a.isFloatReg());
     143          49 :     return a.toFloatReg()->reg();
     144             : }
     145             : 
     146             : static inline FloatRegister
     147           2 : ToFloatRegister(const LAllocation* a)
     148             : {
     149           2 :     return ToFloatRegister(*a);
     150             : }
     151             : 
     152             : static inline FloatRegister
     153          46 : ToFloatRegister(const LDefinition* def)
     154             : {
     155          46 :     return ToFloatRegister(*def->output());
     156             : }
     157             : 
     158             : static inline FloatRegister
     159          12 : ToTempFloatRegisterOrInvalid(const LDefinition* def)
     160             : {
     161          12 :     if (def->isBogusTemp())
     162           0 :         return InvalidFloatReg;
     163          12 :     return ToFloatRegister(def);
     164             : }
     165             : 
     166             : static inline AnyRegister
     167          75 : ToAnyRegister(const LAllocation& a)
     168             : {
     169          75 :     MOZ_ASSERT(a.isGeneralReg() || a.isFloatReg());
     170          75 :     if (a.isGeneralReg())
     171          74 :         return AnyRegister(ToRegister(a));
     172           1 :     return AnyRegister(ToFloatRegister(a));
     173             : }
     174             : 
     175             : static inline AnyRegister
     176          75 : ToAnyRegister(const LAllocation* a)
     177             : {
     178          75 :     return ToAnyRegister(*a);
     179             : }
     180             : 
     181             : static inline AnyRegister
     182          20 : ToAnyRegister(const LDefinition* def)
     183             : {
     184          20 :     return ToAnyRegister(def->output());
     185             : }
     186             : 
     187             : static inline RegisterOrInt32Constant
     188           6 : ToRegisterOrInt32Constant(const LAllocation* a)
     189             : {
     190           6 :     if (a->isConstant())
     191           4 :         return RegisterOrInt32Constant(ToInt32(a));
     192           2 :     return RegisterOrInt32Constant(ToRegister(a));
     193             : }
     194             : 
     195             : static inline ValueOperand
     196          51 : GetValueOutput(LInstruction* ins)
     197             : {
     198             : #if defined(JS_NUNBOX32)
     199             :     return ValueOperand(ToRegister(ins->getDef(TYPE_INDEX)),
     200             :                         ToRegister(ins->getDef(PAYLOAD_INDEX)));
     201             : #elif defined(JS_PUNBOX64)
     202          51 :     return ValueOperand(ToRegister(ins->getDef(0)));
     203             : #else
     204             : #error "Unknown"
     205             : #endif
     206             : }
     207             : 
     208             : static inline ValueOperand
     209             : GetTempValue(Register type, Register payload)
     210             : {
     211             : #if defined(JS_NUNBOX32)
     212             :     return ValueOperand(type, payload);
     213             : #elif defined(JS_PUNBOX64)
     214             :     (void)type;
     215             :     return ValueOperand(payload);
     216             : #else
     217             : #error "Unknown"
     218             : #endif
     219             : }
     220             : 
     221             : int32_t
     222         107 : CodeGeneratorShared::ArgToStackOffset(int32_t slot) const
     223             : {
     224         107 :     return masm.framePushed() +
     225         214 :            (gen->compilingWasm() ? sizeof(wasm::Frame) : sizeof(JitFrameLayout)) +
     226         107 :            slot;
     227             : }
     228             : 
     229             : int32_t
     230         539 : CodeGeneratorShared::SlotToStackOffset(int32_t slot) const
     231             : {
     232         539 :     MOZ_ASSERT(slot > 0 && slot <= int32_t(graph.localSlotCount()));
     233         539 :     int32_t offset = masm.framePushed() - frameInitialAdjustment_ - slot;
     234         539 :     MOZ_ASSERT(offset >= 0);
     235         539 :     return offset;
     236             : }
     237             : 
     238             : int32_t
     239             : CodeGeneratorShared::StackOffsetToSlot(int32_t offset) const
     240             : {
     241             :     // See: SlotToStackOffset. This is used to convert pushed arguments
     242             :     // to a slot index that safepoints can use.
     243             :     //
     244             :     // offset = framePushed - frameInitialAdjustment - slot
     245             :     // offset + slot = framePushed - frameInitialAdjustment
     246             :     // slot = framePushed - frameInitialAdjustement - offset
     247             :     return masm.framePushed() - frameInitialAdjustment_ - offset;
     248             : }
     249             : 
     250             : // For argument construction for calls. Argslots are Value-sized.
     251             : int32_t
     252          98 : CodeGeneratorShared::StackOffsetOfPassedArg(int32_t slot) const
     253             : {
     254             :     // A slot of 0 is permitted only to calculate %esp offset for calls.
     255          98 :     MOZ_ASSERT(slot >= 0 && slot <= int32_t(graph.argumentSlotCount()));
     256         196 :     int32_t offset = masm.framePushed() -
     257         196 :                      graph.paddedLocalSlotsSize() -
     258          98 :                      (slot * sizeof(Value));
     259             : 
     260             :     // Passed arguments go below A function's local stack storage.
     261             :     // When arguments are being pushed, there is nothing important on the stack.
     262             :     // Therefore, It is safe to push the arguments down arbitrarily.  Pushing
     263             :     // by sizeof(Value) is desirable since everything on the stack is a Value.
     264             :     // Note that paddedLocalSlotCount() aligns to at least a Value boundary
     265             :     // specifically to support this.
     266          98 :     MOZ_ASSERT(offset >= 0);
     267          98 :     MOZ_ASSERT(offset % sizeof(Value) == 0);
     268          98 :     return offset;
     269             : }
     270             : 
     271             : int32_t
     272         574 : CodeGeneratorShared::ToStackOffset(LAllocation a) const
     273             : {
     274         574 :     if (a.isArgument())
     275          35 :         return ArgToStackOffset(a.toArgument()->index());
     276         539 :     return SlotToStackOffset(a.toStackSlot()->slot());
     277             : }
     278             : 
     279             : int32_t
     280          32 : CodeGeneratorShared::ToStackOffset(const LAllocation* a) const
     281             : {
     282          32 :     return ToStackOffset(*a);
     283             : }
     284             : 
     285             : Address
     286           0 : CodeGeneratorShared::ToAddress(const LAllocation& a)
     287             : {
     288           0 :     MOZ_ASSERT(a.isMemory());
     289           0 :     return Address(masm.getStackPointer(), ToStackOffset(&a));
     290             : }
     291             : 
     292             : Address
     293           0 : CodeGeneratorShared::ToAddress(const LAllocation* a)
     294             : {
     295           0 :     return ToAddress(*a);
     296             : }
     297             : 
     298             : void
     299          91 : CodeGeneratorShared::saveLive(LInstruction* ins)
     300             : {
     301          91 :     MOZ_ASSERT(!ins->isCall());
     302          91 :     LSafepoint* safepoint = ins->safepoint();
     303          91 :     masm.PushRegsInMask(safepoint->liveRegs());
     304          91 : }
     305             : 
     306             : void
     307          18 : CodeGeneratorShared::restoreLive(LInstruction* ins)
     308             : {
     309          18 :     MOZ_ASSERT(!ins->isCall());
     310          18 :     LSafepoint* safepoint = ins->safepoint();
     311          18 :     masm.PopRegsInMask(safepoint->liveRegs());
     312          18 : }
     313             : 
     314             : void
     315          73 : CodeGeneratorShared::restoreLiveIgnore(LInstruction* ins, LiveRegisterSet ignore)
     316             : {
     317          73 :     MOZ_ASSERT(!ins->isCall());
     318          73 :     LSafepoint* safepoint = ins->safepoint();
     319          73 :     masm.PopRegsInMaskIgnore(safepoint->liveRegs(), ignore);
     320          73 : }
     321             : 
     322             : void
     323           2 : CodeGeneratorShared::saveLiveVolatile(LInstruction* ins)
     324             : {
     325           2 :     MOZ_ASSERT(!ins->isCall());
     326           2 :     LSafepoint* safepoint = ins->safepoint();
     327           2 :     LiveRegisterSet regs;
     328           2 :     regs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(), RegisterSet::Volatile());
     329           2 :     masm.PushRegsInMask(regs);
     330           2 : }
     331             : 
     332             : void
     333           2 : CodeGeneratorShared::restoreLiveVolatile(LInstruction* ins)
     334             : {
     335           2 :     MOZ_ASSERT(!ins->isCall());
     336           2 :     LSafepoint* safepoint = ins->safepoint();
     337           2 :     LiveRegisterSet regs;
     338           2 :     regs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(), RegisterSet::Volatile());
     339           2 :     masm.PopRegsInMask(regs);
     340           2 : }
     341             : 
     342             : void
     343           0 : CodeGeneratorShared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end, bool isLoad,
     344             :                                                  Scalar::Type type, Operand mem, LAllocation alloc)
     345             : {
     346             : #ifdef DEBUG
     347             :     using namespace Disassembler;
     348             : 
     349           0 :     Disassembler::HeapAccess::Kind kind = isLoad ? HeapAccess::Load : HeapAccess::Store;
     350           0 :     switch (type) {
     351             :       case Scalar::Int8:
     352             :       case Scalar::Int16:
     353           0 :         if (kind == HeapAccess::Load)
     354           0 :             kind = HeapAccess::LoadSext32;
     355           0 :         break;
     356             :       default:
     357           0 :         break;
     358             :     }
     359             : 
     360           0 :     OtherOperand op;
     361           0 :     switch (type) {
     362             :       case Scalar::Int8:
     363             :       case Scalar::Uint8:
     364             :       case Scalar::Int16:
     365             :       case Scalar::Uint16:
     366             :       case Scalar::Int32:
     367             :       case Scalar::Uint32:
     368           0 :         if (!alloc.isConstant()) {
     369           0 :             op = OtherOperand(ToRegister(alloc).encoding());
     370             :         } else {
     371             :             // x86 doesn't allow encoding an imm64 to memory move; the value
     372             :             // is wrapped anyways.
     373           0 :             int32_t i = ToInt32(&alloc);
     374             : 
     375             :             // Sign-extend the immediate value out to 32 bits. We do this even
     376             :             // for unsigned element types so that we match what the disassembly
     377             :             // code does, as it doesn't know about signedness of stores.
     378           0 :             unsigned shift = 32 - TypedArrayElemSize(type) * 8;
     379           0 :             i = i << shift >> shift;
     380           0 :             op = OtherOperand(i);
     381             :         }
     382           0 :         break;
     383             :       case Scalar::Int64:
     384             :         // Can't encode an imm64-to-memory move.
     385           0 :         op = OtherOperand(ToRegister(alloc).encoding());
     386           0 :         break;
     387             :       case Scalar::Float32:
     388             :       case Scalar::Float64:
     389             :       case Scalar::Float32x4:
     390             :       case Scalar::Int8x16:
     391             :       case Scalar::Int16x8:
     392             :       case Scalar::Int32x4:
     393           0 :         op = OtherOperand(ToFloatRegister(alloc).encoding());
     394           0 :         break;
     395             :       case Scalar::Uint8Clamped:
     396             :       case Scalar::MaxTypedArrayViewType:
     397           0 :         MOZ_CRASH("Unexpected array type");
     398             :     }
     399             : 
     400           0 :     HeapAccess access(kind, TypedArrayElemSize(type), ComplexAddress(mem), op);
     401           0 :     masm.verifyHeapAccessDisassembly(begin, end, access);
     402             : #endif
     403           0 : }
     404             : 
     405             : void
     406           0 : CodeGeneratorShared::verifyLoadDisassembly(uint32_t begin, uint32_t end, Scalar::Type type,
     407             :                                            Operand mem, LAllocation alloc)
     408             : {
     409           0 :     verifyHeapAccessDisassembly(begin, end, true, type, mem, alloc);
     410           0 : }
     411             : 
     412             : void
     413           0 : CodeGeneratorShared::verifyStoreDisassembly(uint32_t begin, uint32_t end, Scalar::Type type,
     414             :                                             Operand mem, LAllocation alloc)
     415             : {
     416           0 :     verifyHeapAccessDisassembly(begin, end, false, type, mem, alloc);
     417           0 : }
     418             : 
     419             : inline bool
     420           0 : CodeGeneratorShared::isGlobalObject(JSObject* object)
     421             : {
     422             :     // Calling object->is<GlobalObject>() is racy because this relies on
     423             :     // checking the group and this can be changed while we are compiling off the
     424             :     // main thread.
     425           0 :     return object == gen->compartment->maybeGlobal();
     426             : }
     427             : 
     428             : } // namespace jit
     429             : } // namespace js
     430             : 
     431             : #endif /* jit_shared_CodeGenerator_shared_inl_h */

Generated by: LCOV version 1.13