js/src/jit/shared/Lowering-x86-shared.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #include "jit/shared/Lowering-x86-shared.h"
     9 #include "mozilla/MathAlgorithms.h"
    11 #include "jit/MIR.h"
    13 #include "jit/shared/Lowering-shared-inl.h"
    15 using namespace js;
    16 using namespace js::jit;
    18 using mozilla::Abs;
    19 using mozilla::FloorLog2;
    21 LTableSwitch *
    22 LIRGeneratorX86Shared::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
    23                                        MTableSwitch *tableswitch)
    24 {
    25     return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
    26 }
    28 LTableSwitchV *
    29 LIRGeneratorX86Shared::newLTableSwitchV(MTableSwitch *tableswitch)
    30 {
    31     return new(alloc()) LTableSwitchV(temp(), tempDouble(), temp(), tableswitch);
    32 }
    34 bool
    35 LIRGeneratorX86Shared::visitGuardShape(MGuardShape *ins)
    36 {
    37     JS_ASSERT(ins->obj()->type() == MIRType_Object);
    39     LGuardShape *guard = new(alloc()) LGuardShape(useRegister(ins->obj()));
    40     if (!assignSnapshot(guard, ins->bailoutKind()))
    41         return false;
    42     if (!add(guard, ins))
    43         return false;
    44     return redefine(ins, ins->obj());
    45 }
    47 bool
    48 LIRGeneratorX86Shared::visitGuardObjectType(MGuardObjectType *ins)
    49 {
    50     JS_ASSERT(ins->obj()->type() == MIRType_Object);
    52     LGuardObjectType *guard = new(alloc()) LGuardObjectType(useRegister(ins->obj()));
    53     if (!assignSnapshot(guard))
    54         return false;
    55     if (!add(guard, ins))
    56         return false;
    57     return redefine(ins, ins->obj());
    58 }
    60 bool
    61 LIRGeneratorX86Shared::visitPowHalf(MPowHalf *ins)
    62 {
    63     MDefinition *input = ins->input();
    64     JS_ASSERT(input->type() == MIRType_Double);
    65     LPowHalfD *lir = new(alloc()) LPowHalfD(useRegisterAtStart(input));
    66     return defineReuseInput(lir, ins, 0);
    67 }
    69 bool
    70 LIRGeneratorX86Shared::lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
    71                                      MDefinition *lhs, MDefinition *rhs)
    72 {
    73     ins->setOperand(0, useRegisterAtStart(lhs));
    75     // shift operator should be constant or in register ecx
    76     // x86 can't shift a non-ecx register
    77     if (rhs->isConstant())
    78         ins->setOperand(1, useOrConstant(rhs));
    79     else
    80         ins->setOperand(1, useFixed(rhs, ecx));
    82     return defineReuseInput(ins, mir, 0);
    83 }
    85 bool
    86 LIRGeneratorX86Shared::lowerForALU(LInstructionHelper<1, 1, 0> *ins, MDefinition *mir,
    87                                    MDefinition *input)
    88 {
    89     ins->setOperand(0, useRegisterAtStart(input));
    90     return defineReuseInput(ins, mir, 0);
    91 }
    93 bool
    94 LIRGeneratorX86Shared::lowerForALU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
    95                                    MDefinition *lhs, MDefinition *rhs)
    96 {
    97     ins->setOperand(0, useRegisterAtStart(lhs));
    98     ins->setOperand(1, useOrConstant(rhs));
    99     return defineReuseInput(ins, mir, 0);
   100 }
   102 bool
   103 LIRGeneratorX86Shared::lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs, MDefinition *rhs)
   104 {
   105     ins->setOperand(0, useRegisterAtStart(lhs));
   106     ins->setOperand(1, use(rhs));
   107     return defineReuseInput(ins, mir, 0);
   108 }
   110 bool
   111 LIRGeneratorX86Shared::lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
   112                                                MDefinition *lhs, MDefinition *rhs)
   113 {
   114     baab->setOperand(0, useRegisterAtStart(lhs));
   115     baab->setOperand(1, useRegisterOrConstantAtStart(rhs));
   116     return add(baab, mir);
   117 }
   119 bool
   120 LIRGeneratorX86Shared::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
   121 {
   122     // Note: lhs is used twice, so that we can restore the original value for the
   123     // negative zero check.
   124     LMulI *lir = new(alloc()) LMulI(useRegisterAtStart(lhs), useOrConstant(rhs), use(lhs));
   125     if (mul->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   126         return false;
   127     return defineReuseInput(lir, mul, 0);
   128 }
   130 bool
   131 LIRGeneratorX86Shared::lowerDivI(MDiv *div)
   132 {
   133     if (div->isUnsigned())
   134         return lowerUDiv(div);
   136     // Division instructions are slow. Division by constant denominators can be
   137     // rewritten to use other instructions.
   138     if (div->rhs()->isConstant()) {
   139         int32_t rhs = div->rhs()->toConstant()->value().toInt32();
   141         // Division by powers of two can be done by shifting, and division by
   142         // other numbers can be done by a reciprocal multiplication technique.
   143         int32_t shift = FloorLog2(Abs(rhs));
   144         if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
   145             LAllocation lhs = useRegisterAtStart(div->lhs());
   146             LDivPowTwoI *lir;
   147             if (!div->canBeNegativeDividend()) {
   148                 // Numerator is unsigned, so does not need adjusting.
   149                 lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift, rhs < 0);
   150             } else {
   151                 // Numerator is signed, and needs adjusting, and an extra
   152                 // lhs copy register is needed.
   153                 lir = new(alloc()) LDivPowTwoI(lhs, useRegister(div->lhs()), shift, rhs < 0);
   154             }
   155             if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   156                 return false;
   157             return defineReuseInput(lir, div, 0);
   158         }
   159     }
   161     LDivI *lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()),
   162                                     tempFixed(edx));
   163     if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   164         return false;
   165     return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
   166 }
   168 bool
   169 LIRGeneratorX86Shared::lowerModI(MMod *mod)
   170 {
   171     if (mod->isUnsigned())
   172         return lowerUMod(mod);
   174     if (mod->rhs()->isConstant()) {
   175         int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
   176         int32_t shift = FloorLog2(Abs(rhs));
   177         if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
   178             LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
   179             if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   180                 return false;
   181             return defineReuseInput(lir, mod, 0);
   182         }
   183     }
   185     LModI *lir = new(alloc()) LModI(useRegister(mod->lhs()),
   186                                     useRegister(mod->rhs()),
   187                                     tempFixed(eax));
   188     if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   189         return false;
   190     return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
   191 }
   193 bool
   194 LIRGeneratorX86Shared::visitAsmJSNeg(MAsmJSNeg *ins)
   195 {
   196     if (ins->type() == MIRType_Int32)
   197         return defineReuseInput(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins, 0);
   199     if (ins->type() == MIRType_Float32)
   200         return defineReuseInput(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins, 0);
   202     JS_ASSERT(ins->type() == MIRType_Double);
   203     return defineReuseInput(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins, 0);
   204 }
   206 bool
   207 LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
   208 {
   209     LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(div->lhs()),
   210                                               useRegister(div->rhs()),
   211                                               tempFixed(edx));
   212     if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   213         return false;
   214     return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
   215 }
   217 bool
   218 LIRGeneratorX86Shared::lowerUMod(MMod *mod)
   219 {
   220     LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(mod->lhs()),
   221                                               useRegister(mod->rhs()),
   222                                               tempFixed(eax));
   223     if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
   224         return false;
   225     return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
   226 }
   228 bool
   229 LIRGeneratorX86Shared::lowerUrshD(MUrsh *mir)
   230 {
   231     MDefinition *lhs = mir->lhs();
   232     MDefinition *rhs = mir->rhs();
   234     JS_ASSERT(lhs->type() == MIRType_Int32);
   235     JS_ASSERT(rhs->type() == MIRType_Int32);
   236     JS_ASSERT(mir->type() == MIRType_Double);
   238 #ifdef JS_CODEGEN_X64
   239     JS_ASSERT(ecx == rcx);
   240 #endif
   242     LUse lhsUse = useRegisterAtStart(lhs);
   243     LAllocation rhsAlloc = rhs->isConstant() ? useOrConstant(rhs) : useFixed(rhs, ecx);
   245     LUrshD *lir = new(alloc()) LUrshD(lhsUse, rhsAlloc, tempCopy(lhs, 0));
   246     return define(lir, mir);
   247 }
   249 bool
   250 LIRGeneratorX86Shared::lowerConstantDouble(double d, MInstruction *mir)
   251 {
   252     return define(new(alloc()) LDouble(d), mir);
   253 }
   255 bool
   256 LIRGeneratorX86Shared::lowerConstantFloat32(float f, MInstruction *mir)
   257 {
   258     return define(new(alloc()) LFloat32(f), mir);
   259 }
   261 bool
   262 LIRGeneratorX86Shared::visitConstant(MConstant *ins)
   263 {
   264     if (ins->type() == MIRType_Double)
   265         return lowerConstantDouble(ins->value().toDouble(), ins);
   267     if (ins->type() == MIRType_Float32)
   268         return lowerConstantFloat32(ins->value().toDouble(), ins);
   270     // Emit non-double constants at their uses.
   271     if (ins->canEmitAtUses())
   272         return emitAtUses(ins);
   274     return LIRGeneratorShared::visitConstant(ins);
   275 }
   277 bool
   278 LIRGeneratorX86Shared::lowerTruncateDToInt32(MTruncateToInt32 *ins)
   279 {
   280     MDefinition *opd = ins->input();
   281     JS_ASSERT(opd->type() == MIRType_Double);
   283     LDefinition maybeTemp = Assembler::HasSSE3() ? LDefinition::BogusTemp() : tempDouble();
   284     return define(new(alloc()) LTruncateDToInt32(useRegister(opd), maybeTemp), ins);
   285 }
   287 bool
   288 LIRGeneratorX86Shared::lowerTruncateFToInt32(MTruncateToInt32 *ins)
   289 {
   290     MDefinition *opd = ins->input();
   291     JS_ASSERT(opd->type() == MIRType_Float32);
   293     LDefinition maybeTemp = Assembler::HasSSE3() ? LDefinition::BogusTemp() : tempFloat32();
   294     return define(new(alloc()) LTruncateFToInt32(useRegister(opd), maybeTemp), ins);
   295 }
   297 bool
   298 LIRGeneratorX86Shared::visitForkJoinGetSlice(MForkJoinGetSlice *ins)
   299 {
   300     // We fix eax and edx for cmpxchg and div.
   301     LForkJoinGetSlice *lir = new(alloc())
   302         LForkJoinGetSlice(useFixed(ins->forkJoinContext(), ForkJoinGetSliceReg_cx),
   303                           tempFixed(eax),
   304                           tempFixed(edx),
   305                           tempFixed(ForkJoinGetSliceReg_temp0),
   306                           tempFixed(ForkJoinGetSliceReg_temp1));
   307     return defineFixed(lir, ins, LAllocation(AnyRegister(ForkJoinGetSliceReg_output)));
   308 }

mercurial