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.

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

mercurial