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/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.cmpl(R0.payloadReg(), R1.payloadReg());
32 masm.setCC(cond, R0.payloadReg());
33 masm.movzbl(R0.payloadReg(), R0.payloadReg());
35 // Box the result and return
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);
42 return true;
43 }
45 // ICBinaryArith_Int32
47 bool
48 ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
49 {
50 // Guard that R0 is an integer and R1 is an integer.
51 Label failure;
52 masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
53 masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
55 // Add R0 and R1. Don't need to explicitly unbox, just use the TailCallReg which
56 // should be available.
57 Register scratchReg = BaselineTailCallReg;
59 Label revertRegister, maybeNegZero;
60 switch(op_) {
61 case JSOP_ADD:
62 // Add R0 and R1. Don't need to explicitly unbox.
63 masm.movl(R0.payloadReg(), scratchReg);
64 masm.addl(R1.payloadReg(), scratchReg);
66 // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
67 // the next stub.
68 masm.j(Assembler::Overflow, &failure);
70 // Just overwrite the payload, the tag is still fine.
71 masm.movl(scratchReg, R0.payloadReg());
72 break;
73 case JSOP_SUB:
74 masm.movl(R0.payloadReg(), scratchReg);
75 masm.subl(R1.payloadReg(), scratchReg);
76 masm.j(Assembler::Overflow, &failure);
77 masm.movl(scratchReg, R0.payloadReg());
78 break;
79 case JSOP_MUL:
80 masm.movl(R0.payloadReg(), scratchReg);
81 masm.imull(R1.payloadReg(), scratchReg);
82 masm.j(Assembler::Overflow, &failure);
84 masm.testl(scratchReg, scratchReg);
85 masm.j(Assembler::Zero, &maybeNegZero);
87 masm.movl(scratchReg, R0.payloadReg());
88 break;
89 case JSOP_DIV:
90 {
91 // Prevent division by 0.
92 masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
94 // Prevent negative 0 and -2147483648 / -1.
95 masm.branch32(Assembler::Equal, R0.payloadReg(), Imm32(INT32_MIN), &failure);
97 Label notZero;
98 masm.branch32(Assembler::NotEqual, R0.payloadReg(), Imm32(0), ¬Zero);
99 masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &failure);
100 masm.bind(¬Zero);
102 // For idiv we need eax.
103 JS_ASSERT(R1.typeReg() == eax);
104 masm.movl(R0.payloadReg(), eax);
105 // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
106 masm.movl(R0.payloadReg(), scratchReg);
107 // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
108 masm.cdq();
109 masm.idiv(R1.payloadReg());
111 // A remainder implies a double result.
112 masm.branchTest32(Assembler::NonZero, edx, edx, &revertRegister);
114 masm.movl(eax, R0.payloadReg());
115 break;
116 }
117 case JSOP_MOD:
118 {
119 // x % 0 always results in NaN.
120 masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
122 // Prevent negative 0 and -2147483648 % -1.
123 masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
125 // For idiv we need eax.
126 JS_ASSERT(R1.typeReg() == eax);
127 masm.movl(R0.payloadReg(), eax);
128 // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
129 masm.movl(R0.payloadReg(), scratchReg);
130 // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
131 masm.cdq();
132 masm.idiv(R1.payloadReg());
134 // Fail when we would need a negative remainder.
135 Label done;
136 masm.branchTest32(Assembler::NonZero, edx, edx, &done);
137 masm.branchTest32(Assembler::Signed, scratchReg, scratchReg, &revertRegister);
138 masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &revertRegister);
140 masm.bind(&done);
141 // Result is in edx, tag in ecx remains untouched.
142 JS_ASSERT(R0.payloadReg() == edx);
143 JS_ASSERT(R0.typeReg() == ecx);
144 break;
145 }
146 case JSOP_BITOR:
147 // We can overide R0, because the instruction is unfailable.
148 // The R0.typeReg() is also still intact.
149 masm.orl(R1.payloadReg(), R0.payloadReg());
150 break;
151 case JSOP_BITXOR:
152 masm.xorl(R1.payloadReg(), R0.payloadReg());
153 break;
154 case JSOP_BITAND:
155 masm.andl(R1.payloadReg(), R0.payloadReg());
156 break;
157 case JSOP_LSH:
158 // RHS needs to be in ecx for shift operations.
159 JS_ASSERT(R0.typeReg() == ecx);
160 masm.movl(R1.payloadReg(), ecx);
161 masm.shll_cl(R0.payloadReg());
162 // We need to tag again, because we overwrote it.
163 masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
164 break;
165 case JSOP_RSH:
166 masm.movl(R1.payloadReg(), ecx);
167 masm.sarl_cl(R0.payloadReg());
168 masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
169 break;
170 case JSOP_URSH:
171 if (!allowDouble_)
172 masm.movl(R0.payloadReg(), scratchReg);
174 masm.movl(R1.payloadReg(), ecx);
175 masm.shrl_cl(R0.payloadReg());
176 masm.testl(R0.payloadReg(), R0.payloadReg());
177 if (allowDouble_) {
178 Label toUint;
179 masm.j(Assembler::Signed, &toUint);
181 // Box and return.
182 masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
183 EmitReturnFromIC(masm);
185 masm.bind(&toUint);
186 masm.convertUInt32ToDouble(R0.payloadReg(), ScratchFloatReg);
187 masm.boxDouble(ScratchFloatReg, R0);
188 } else {
189 masm.j(Assembler::Signed, &revertRegister);
190 masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
191 }
192 break;
193 default:
194 MOZ_ASSUME_UNREACHABLE("Unhandled op for BinaryArith_Int32. ");
195 }
197 // Return.
198 EmitReturnFromIC(masm);
200 switch(op_) {
201 case JSOP_MUL:
202 masm.bind(&maybeNegZero);
204 // Result is -0 if exactly one of lhs or rhs is negative.
205 masm.movl(R0.payloadReg(), scratchReg);
206 masm.orl(R1.payloadReg(), scratchReg);
207 masm.j(Assembler::Signed, &failure);
209 // Result is +0.
210 masm.mov(ImmWord(0), R0.payloadReg());
211 EmitReturnFromIC(masm);
212 break;
213 case JSOP_DIV:
214 case JSOP_MOD:
215 masm.bind(&revertRegister);
216 masm.movl(scratchReg, R0.payloadReg());
217 masm.movl(ImmType(JSVAL_TYPE_INT32), R1.typeReg());
218 break;
219 case JSOP_URSH:
220 // Revert the content of R0 in the fallible >>> case.
221 if (!allowDouble_) {
222 masm.bind(&revertRegister);
223 masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
224 }
225 break;
226 default:
227 // No special failure handling required.
228 // Fall through to failure.
229 break;
230 }
232 // Failure case - jump to next stub
233 masm.bind(&failure);
234 EmitStubGuardFailure(masm);
236 return true;
237 }
239 bool
240 ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
241 {
242 Label failure;
243 masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
245 switch (op) {
246 case JSOP_BITNOT:
247 masm.notl(R0.payloadReg());
248 break;
249 case JSOP_NEG:
250 // Guard against 0 and MIN_INT, both result in a double.
251 masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
252 masm.negl(R0.payloadReg());
253 break;
254 default:
255 MOZ_ASSUME_UNREACHABLE("Unexpected op");
256 }
258 EmitReturnFromIC(masm);
260 masm.bind(&failure);
261 EmitStubGuardFailure(masm);
262 return true;
263 }
265 } // namespace jit
266 } // namespace js