Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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