Wed, 31 Dec 2014 06:09:35 +0100
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/BaselineHelpers.h"
8 #include "jit/BaselineIC.h"
10 using namespace js;
11 using namespace js::jit;
13 namespace js {
14 namespace jit {
16 // ICCompare_Int32
18 bool
19 ICCompare_Int32::Compiler::generateStubCode(MacroAssembler &masm)
20 {
21 // Guard that R0 is an integer and R1 is an integer.
22 Label failure;
23 masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
24 masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
26 // Directly compare the int32 payload of R0 and R1.
27 Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
28 masm.mov(ImmWord(0), ScratchReg);
29 masm.cmpl(R0.valueReg(), R1.valueReg());
30 masm.setCC(cond, ScratchReg);
32 // Box the result and return
33 masm.boxValue(JSVAL_TYPE_BOOLEAN, ScratchReg, R0.valueReg());
34 EmitReturnFromIC(masm);
36 // Failure case - jump to next stub
37 masm.bind(&failure);
38 EmitStubGuardFailure(masm);
40 return true;
41 }
43 // ICBinaryArith_Int32
45 bool
46 ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
47 {
48 // Guard that R0 is an integer and R1 is an integer.
49 Label failure;
50 masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
51 masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
53 Label revertRegister, maybeNegZero;
54 switch(op_) {
55 case JSOP_ADD:
56 masm.unboxInt32(R0, ExtractTemp0);
57 // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
58 // the next stub.
59 masm.addl(R1.valueReg(), ExtractTemp0);
60 masm.j(Assembler::Overflow, &failure);
62 // Box the result
63 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
64 break;
65 case JSOP_SUB:
66 masm.unboxInt32(R0, ExtractTemp0);
67 masm.subl(R1.valueReg(), ExtractTemp0);
68 masm.j(Assembler::Overflow, &failure);
69 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
70 break;
71 case JSOP_MUL:
72 masm.unboxInt32(R0, ExtractTemp0);
73 masm.imull(R1.valueReg(), ExtractTemp0);
74 masm.j(Assembler::Overflow, &failure);
76 masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &maybeNegZero);
78 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
79 break;
80 case JSOP_DIV:
81 {
82 JS_ASSERT(R2.scratchReg() == rax);
83 JS_ASSERT(R0.valueReg() != rdx);
84 JS_ASSERT(R1.valueReg() != rdx);
85 masm.unboxInt32(R0, eax);
86 masm.unboxInt32(R1, ExtractTemp0);
88 // Prevent division by 0.
89 masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
91 // Prevent negative 0 and -2147483648 / -1.
92 masm.branch32(Assembler::Equal, eax, Imm32(INT32_MIN), &failure);
94 Label notZero;
95 masm.branch32(Assembler::NotEqual, eax, Imm32(0), ¬Zero);
96 masm.branchTest32(Assembler::Signed, ExtractTemp0, ExtractTemp0, &failure);
97 masm.bind(¬Zero);
99 // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
100 masm.cdq();
101 masm.idiv(ExtractTemp0);
103 // A remainder implies a double result.
104 masm.branchTest32(Assembler::NonZero, edx, edx, &failure);
106 masm.boxValue(JSVAL_TYPE_INT32, eax, R0.valueReg());
107 break;
108 }
109 case JSOP_MOD:
110 {
111 JS_ASSERT(R2.scratchReg() == rax);
112 JS_ASSERT(R0.valueReg() != rdx);
113 JS_ASSERT(R1.valueReg() != rdx);
114 masm.unboxInt32(R0, eax);
115 masm.unboxInt32(R1, ExtractTemp0);
117 // x % 0 always results in NaN.
118 masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
120 // Prevent negative 0 and -2147483648 % -1.
121 masm.branchTest32(Assembler::Zero, eax, Imm32(0x7fffffff), &failure);
123 // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
124 masm.cdq();
125 masm.idiv(ExtractTemp0);
127 // Fail when we would need a negative remainder.
128 Label done;
129 masm.branchTest32(Assembler::NonZero, edx, edx, &done);
130 masm.orl(ExtractTemp0, eax);
131 masm.branchTest32(Assembler::Signed, eax, eax, &failure);
133 masm.bind(&done);
134 masm.boxValue(JSVAL_TYPE_INT32, edx, R0.valueReg());
135 break;
136 }
137 case JSOP_BITOR:
138 // We can overide R0, because the instruction is unfailable.
139 // Because the tag bits are the same, we don't need to retag.
140 masm.orq(R1.valueReg(), R0.valueReg());
141 break;
142 case JSOP_BITXOR:
143 masm.xorl(R1.valueReg(), R0.valueReg());
144 masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
145 break;
146 case JSOP_BITAND:
147 masm.andq(R1.valueReg(), R0.valueReg());
148 break;
149 case JSOP_LSH:
150 masm.unboxInt32(R0, ExtractTemp0);
151 masm.unboxInt32(R1, ecx); // Unboxing R1 to ecx, clobbers R0.
152 masm.shll_cl(ExtractTemp0);
153 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
154 break;
155 case JSOP_RSH:
156 masm.unboxInt32(R0, ExtractTemp0);
157 masm.unboxInt32(R1, ecx);
158 masm.sarl_cl(ExtractTemp0);
159 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
160 break;
161 case JSOP_URSH:
162 if (!allowDouble_)
163 masm.movq(R0.valueReg(), ScratchReg);
165 masm.unboxInt32(R0, ExtractTemp0);
166 masm.unboxInt32(R1, ecx); // This clobbers R0
168 masm.shrl_cl(ExtractTemp0);
169 masm.testl(ExtractTemp0, ExtractTemp0);
170 if (allowDouble_) {
171 Label toUint;
172 masm.j(Assembler::Signed, &toUint);
174 // Box and return.
175 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
176 EmitReturnFromIC(masm);
178 masm.bind(&toUint);
179 masm.convertUInt32ToDouble(ExtractTemp0, ScratchFloatReg);
180 masm.boxDouble(ScratchFloatReg, R0);
181 } else {
182 masm.j(Assembler::Signed, &revertRegister);
183 masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
184 }
185 break;
186 default:
187 MOZ_ASSUME_UNREACHABLE("Unhandled op in BinaryArith_Int32");
188 }
190 // Return from stub.
191 EmitReturnFromIC(masm);
193 if (op_ == JSOP_MUL) {
194 masm.bind(&maybeNegZero);
196 // Result is -0 if exactly one of lhs or rhs is negative.
197 masm.movl(R0.valueReg(), ScratchReg);
198 masm.orl(R1.valueReg(), ScratchReg);
199 masm.j(Assembler::Signed, &failure);
201 // Result is +0.
202 masm.moveValue(Int32Value(0), R0);
203 EmitReturnFromIC(masm);
204 }
206 // Revert the content of R0 in the fallible >>> case.
207 if (op_ == JSOP_URSH && !allowDouble_) {
208 masm.bind(&revertRegister);
209 // Restore tag and payload.
210 masm.movq(ScratchReg, R0.valueReg());
211 // Fall through to failure.
212 }
213 // Failure case - jump to next stub
214 masm.bind(&failure);
215 EmitStubGuardFailure(masm);
217 return true;
218 }
220 bool
221 ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
222 {
223 Label failure;
224 masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
226 switch (op) {
227 case JSOP_BITNOT:
228 masm.notl(R0.valueReg());
229 break;
230 case JSOP_NEG:
231 // Guard against 0 and MIN_INT, both result in a double.
232 masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
233 masm.negl(R0.valueReg());
234 break;
235 default:
236 MOZ_ASSUME_UNREACHABLE("Unexpected op");
237 }
239 masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
241 EmitReturnFromIC(masm);
243 masm.bind(&failure);
244 EmitStubGuardFailure(masm);
245 return true;
246 }
248 } // namespace jit
249 } // namespace js