js/src/jit/arm/BaselineIC-arm.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/BaselineCompiler.h"
     8 #include "jit/BaselineHelpers.h"
     9 #include "jit/BaselineIC.h"
    10 #include "jit/BaselineJIT.h"
    11 #include "jit/IonLinker.h"
    13 using namespace js;
    14 using namespace js::jit;
    16 namespace js {
    17 namespace jit {
    19 // ICCompare_Int32
    21 bool
    22 ICCompare_Int32::Compiler::generateStubCode(MacroAssembler &masm)
    23 {
    24     // Guard that R0 is an integer and R1 is an integer.
    25     Label failure;
    26     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    27     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
    29     // Compare payload regs of R0 and R1.
    30     Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
    31     masm.cmp32(R0.payloadReg(), R1.payloadReg());
    32     masm.ma_mov(Imm32(1), R0.payloadReg(), NoSetCond, cond);
    33     masm.ma_mov(Imm32(0), R0.payloadReg(), NoSetCond, Assembler::InvertCondition(cond));
    35     // Result is implicitly boxed already.
    36     masm.tagValue(JSVAL_TYPE_BOOLEAN, R0.payloadReg(), R0);
    37     EmitReturnFromIC(masm);
    39     // Failure case - jump to next stub
    40     masm.bind(&failure);
    41     EmitStubGuardFailure(masm);
    43     return true;
    44 }
    46 bool
    47 ICCompare_Double::Compiler::generateStubCode(MacroAssembler &masm)
    48 {
    49     Label failure, isNaN;
    50     masm.ensureDouble(R0, FloatReg0, &failure);
    51     masm.ensureDouble(R1, FloatReg1, &failure);
    53     Register dest = R0.scratchReg();
    55     Assembler::DoubleCondition doubleCond = JSOpToDoubleCondition(op);
    56     Assembler::Condition cond = Assembler::ConditionFromDoubleCondition(doubleCond);
    58     masm.compareDouble(FloatReg0, FloatReg1);
    59     masm.ma_mov(Imm32(0), dest);
    60     masm.ma_mov(Imm32(1), dest, NoSetCond, cond);
    62     masm.tagValue(JSVAL_TYPE_BOOLEAN, dest, R0);
    63     EmitReturnFromIC(masm);
    65     // Failure case - jump to next stub
    66     masm.bind(&failure);
    67     EmitStubGuardFailure(masm);
    68     return true;
    69 }
    71 // ICBinaryArith_Int32
    73 extern "C" {
    74     extern int64_t __aeabi_idivmod(int,int);
    75 }
    77 bool
    78 ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
    79 {
    80     // Guard that R0 is an integer and R1 is an integer.
    81     Label failure;
    82     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    83     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
    85     // Add R0 and R1.  Don't need to explicitly unbox, just use R2's payloadReg.
    86     Register scratchReg = R2.payloadReg();
    88     // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
    89     GeneralRegisterSet savedRegs = availableGeneralRegs(2);
    90     savedRegs = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
    91     ValueOperand savedValue = savedRegs.takeAnyValue();
    93     Label maybeNegZero, revertRegister;
    94     switch(op_) {
    95       case JSOP_ADD:
    96         masm.ma_add(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCond);
    98         // Just jump to failure on overflow.  R0 and R1 are preserved, so we can just jump to
    99         // the next stub.
   100         masm.j(Assembler::Overflow, &failure);
   102         // Box the result and return.  We know R0.typeReg() already contains the integer
   103         // tag, so we just need to move the result value into place.
   104         masm.mov(scratchReg, R0.payloadReg());
   105         break;
   106       case JSOP_SUB:
   107         masm.ma_sub(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCond);
   108         masm.j(Assembler::Overflow, &failure);
   109         masm.mov(scratchReg, R0.payloadReg());
   110         break;
   111       case JSOP_MUL: {
   112         Assembler::Condition cond = masm.ma_check_mul(R0.payloadReg(), R1.payloadReg(), scratchReg,
   113                                                       Assembler::Overflow);
   114         masm.j(cond, &failure);
   116         masm.ma_cmp(scratchReg, Imm32(0));
   117         masm.j(Assembler::Equal, &maybeNegZero);
   119         masm.mov(scratchReg, R0.payloadReg());
   120         break;
   121       }
   122       case JSOP_DIV:
   123       case JSOP_MOD: {
   124         // Check for INT_MIN / -1, it results in a double.
   125         masm.ma_cmp(R0.payloadReg(), Imm32(INT_MIN));
   126         masm.ma_cmp(R1.payloadReg(), Imm32(-1), Assembler::Equal);
   127         masm.j(Assembler::Equal, &failure);
   129         // Check for both division by zero and 0 / X with X < 0 (results in -0).
   130         masm.ma_cmp(R1.payloadReg(), Imm32(0));
   131         masm.ma_cmp(R0.payloadReg(), Imm32(0), Assembler::LessThan);
   132         masm.j(Assembler::Equal, &failure);
   134         // The call will preserve registers r4-r11. Save R0 and the link register.
   135         JS_ASSERT(R1 == ValueOperand(r5, r4));
   136         JS_ASSERT(R0 == ValueOperand(r3, r2));
   137         masm.moveValue(R0, savedValue);
   139         masm.setupAlignedABICall(2);
   140         masm.passABIArg(R0.payloadReg());
   141         masm.passABIArg(R1.payloadReg());
   142         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, __aeabi_idivmod));
   144         // idivmod returns the quotient in r0, and the remainder in r1.
   145         if (op_ == JSOP_DIV) {
   146             // Result is a double if the remainder != 0.
   147             masm.branch32(Assembler::NotEqual, r1, Imm32(0), &revertRegister);
   148             masm.tagValue(JSVAL_TYPE_INT32, r0, R0);
   149         } else {
   150             // If X % Y == 0 and X < 0, the result is -0.
   151             Label done;
   152             masm.branch32(Assembler::NotEqual, r1, Imm32(0), &done);
   153             masm.branch32(Assembler::LessThan, savedValue.payloadReg(), Imm32(0), &revertRegister);
   154             masm.bind(&done);
   155             masm.tagValue(JSVAL_TYPE_INT32, r1, R0);
   156         }
   157         break;
   158       }
   159       case JSOP_BITOR:
   160         masm.ma_orr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
   161         break;
   162       case JSOP_BITXOR:
   163         masm.ma_eor(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
   164         break;
   165       case JSOP_BITAND:
   166         masm.ma_and(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
   167         break;
   168       case JSOP_LSH:
   169         // ARM will happily try to shift by more than 0x1f.
   170         masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
   171         masm.ma_lsl(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
   172         break;
   173       case JSOP_RSH:
   174         masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
   175         masm.ma_asr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
   176         break;
   177       case JSOP_URSH:
   178         masm.ma_and(Imm32(0x1F), R1.payloadReg(), scratchReg);
   179         masm.ma_lsr(scratchReg, R0.payloadReg(), scratchReg);
   180         masm.ma_cmp(scratchReg, Imm32(0));
   181         if (allowDouble_) {
   182             Label toUint;
   183             masm.j(Assembler::LessThan, &toUint);
   185             // Move result and box for return.
   186             masm.mov(scratchReg, R0.payloadReg());
   187             EmitReturnFromIC(masm);
   189             masm.bind(&toUint);
   190             masm.convertUInt32ToDouble(scratchReg, ScratchFloatReg);
   191             masm.boxDouble(ScratchFloatReg, R0);
   192         } else {
   193             masm.j(Assembler::LessThan, &failure);
   194             // Move result for return.
   195             masm.mov(scratchReg, R0.payloadReg());
   196         }
   197         break;
   198       default:
   199         MOZ_ASSUME_UNREACHABLE("Unhandled op for BinaryArith_Int32.");
   200     }
   202     EmitReturnFromIC(masm);
   204     switch (op_) {
   205       case JSOP_MUL:
   206         masm.bind(&maybeNegZero);
   208         // Result is -0 if exactly one of lhs or rhs is negative.
   209         masm.ma_cmn(R0.payloadReg(), R1.payloadReg());
   210         masm.j(Assembler::Signed, &failure);
   212         // Result is +0.
   213         masm.ma_mov(Imm32(0), R0.payloadReg());
   214         EmitReturnFromIC(masm);
   215         break;
   216       case JSOP_DIV:
   217       case JSOP_MOD:
   218         masm.bind(&revertRegister);
   219         masm.moveValue(savedValue, R0);
   220         break;
   221       default:
   222         break;
   223     }
   225     // Failure case - jump to next stub
   226     masm.bind(&failure);
   227     EmitStubGuardFailure(masm);
   229     return true;
   230 }
   232 bool
   233 ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
   234 {
   235     Label failure;
   236     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
   238     switch (op) {
   239       case JSOP_BITNOT:
   240         masm.ma_mvn(R0.payloadReg(), R0.payloadReg());
   241         break;
   242       case JSOP_NEG:
   243         // Guard against 0 and MIN_INT, both result in a double.
   244         masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
   246         // Compile -x as 0 - x.
   247         masm.ma_rsb(R0.payloadReg(), Imm32(0), R0.payloadReg());
   248         break;
   249       default:
   250         MOZ_ASSUME_UNREACHABLE("Unexpected op");
   251     }
   253     EmitReturnFromIC(masm);
   255     masm.bind(&failure);
   256     EmitStubGuardFailure(masm);
   257     return true;
   258 }
   260 } // namespace jit
   261 } // namespace js

mercurial