• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25 
26 #include "config.h"
27 
28 #if ENABLE(JIT)
29 #if USE(JSVALUE32_64)
30 #include "JIT.h"
31 
32 #include "CodeBlock.h"
33 #include "JITInlineMethods.h"
34 #include "JITStubCall.h"
35 #include "JITStubs.h"
36 #include "JSArray.h"
37 #include "JSFunction.h"
38 #include "Interpreter.h"
39 #include "ResultType.h"
40 #include "SamplingTool.h"
41 
42 #ifndef NDEBUG
43 #include <stdio.h>
44 #endif
45 
46 using namespace std;
47 
48 namespace JSC {
49 
emit_op_negate(Instruction * currentInstruction)50 void JIT::emit_op_negate(Instruction* currentInstruction)
51 {
52     unsigned dst = currentInstruction[1].u.operand;
53     unsigned src = currentInstruction[2].u.operand;
54 
55     emitLoad(src, regT1, regT0);
56 
57     Jump srcNotInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
58     addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff)));
59     neg32(regT0);
60     emitStoreInt32(dst, regT0, (dst == src));
61 
62     Jump end = jump();
63 
64     srcNotInt.link(this);
65     addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
66 
67     xor32(TrustedImm32(1 << 31), regT1);
68     store32(regT1, tagFor(dst));
69     if (dst != src)
70         store32(regT0, payloadFor(dst));
71 
72     end.link(this);
73 }
74 
emitSlow_op_negate(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)75 void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
76 {
77     unsigned dst = currentInstruction[1].u.operand;
78 
79     linkSlowCase(iter); // 0x7fffffff check
80     linkSlowCase(iter); // double check
81 
82     JITStubCall stubCall(this, cti_op_negate);
83     stubCall.addArgument(regT1, regT0);
84     stubCall.call(dst);
85 }
86 
emit_op_jnless(Instruction * currentInstruction)87 void JIT::emit_op_jnless(Instruction* currentInstruction)
88 {
89     unsigned op1 = currentInstruction[1].u.operand;
90     unsigned op2 = currentInstruction[2].u.operand;
91     unsigned target = currentInstruction[3].u.operand;
92 
93     JumpList notInt32Op1;
94     JumpList notInt32Op2;
95 
96     // Character less.
97     if (isOperandConstantImmediateChar(op1)) {
98         emitLoad(op2, regT1, regT0);
99         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
100         JumpList failures;
101         emitLoadCharacterString(regT0, regT0, failures);
102         addSlowCase(failures);
103         addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
104         return;
105     }
106     if (isOperandConstantImmediateChar(op2)) {
107         emitLoad(op1, regT1, regT0);
108         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
109         JumpList failures;
110         emitLoadCharacterString(regT0, regT0, failures);
111         addSlowCase(failures);
112         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
113         return;
114     }
115     if (isOperandConstantImmediateInt(op1)) {
116         // Int32 less.
117         emitLoad(op2, regT3, regT2);
118         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
119         addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
120     } else if (isOperandConstantImmediateInt(op2)) {
121         emitLoad(op1, regT1, regT0);
122         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
123         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
124     } else {
125         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
126         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
127         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
128         addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
129     }
130 
131     if (!supportsFloatingPoint()) {
132         addSlowCase(notInt32Op1);
133         addSlowCase(notInt32Op2);
134         return;
135     }
136     Jump end = jump();
137 
138     // Double less.
139     emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
140     end.link(this);
141 }
142 
emitSlow_op_jnless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)143 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
144 {
145     unsigned op1 = currentInstruction[1].u.operand;
146     unsigned op2 = currentInstruction[2].u.operand;
147     unsigned target = currentInstruction[3].u.operand;
148 
149     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
150         linkSlowCase(iter);
151         linkSlowCase(iter);
152         linkSlowCase(iter);
153         linkSlowCase(iter);
154     } else {
155         if (!supportsFloatingPoint()) {
156             if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
157                 linkSlowCase(iter); // int32 check
158             linkSlowCase(iter); // int32 check
159         } else {
160             if (!isOperandConstantImmediateInt(op1)) {
161                 linkSlowCase(iter); // double check
162                 linkSlowCase(iter); // int32 check
163             }
164             if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
165                 linkSlowCase(iter); // double check
166         }
167     }
168 
169     JITStubCall stubCall(this, cti_op_jless);
170     stubCall.addArgument(op1);
171     stubCall.addArgument(op2);
172     stubCall.call();
173     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
174 }
175 
emit_op_jless(Instruction * currentInstruction)176 void JIT::emit_op_jless(Instruction* currentInstruction)
177 {
178     unsigned op1 = currentInstruction[1].u.operand;
179     unsigned op2 = currentInstruction[2].u.operand;
180     unsigned target = currentInstruction[3].u.operand;
181 
182     JumpList notInt32Op1;
183     JumpList notInt32Op2;
184 
185     // Character less.
186     if (isOperandConstantImmediateChar(op1)) {
187         emitLoad(op2, regT1, regT0);
188         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
189         JumpList failures;
190         emitLoadCharacterString(regT0, regT0, failures);
191         addSlowCase(failures);
192         addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
193         return;
194     }
195     if (isOperandConstantImmediateChar(op2)) {
196         emitLoad(op1, regT1, regT0);
197         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
198         JumpList failures;
199         emitLoadCharacterString(regT0, regT0, failures);
200         addSlowCase(failures);
201         addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
202         return;
203     }
204     if (isOperandConstantImmediateInt(op1)) {
205         emitLoad(op2, regT3, regT2);
206         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
207         addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
208     } else if (isOperandConstantImmediateInt(op2)) {
209         emitLoad(op1, regT1, regT0);
210         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
211         addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
212     } else {
213         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
214         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
215         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
216         addJump(branch32(LessThan, regT0, regT2), target);
217     }
218 
219     if (!supportsFloatingPoint()) {
220         addSlowCase(notInt32Op1);
221         addSlowCase(notInt32Op2);
222         return;
223     }
224     Jump end = jump();
225 
226     // Double less.
227     emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
228     end.link(this);
229 }
230 
emitSlow_op_jless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)231 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
232 {
233     unsigned op1 = currentInstruction[1].u.operand;
234     unsigned op2 = currentInstruction[2].u.operand;
235     unsigned target = currentInstruction[3].u.operand;
236 
237     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
238         linkSlowCase(iter);
239         linkSlowCase(iter);
240         linkSlowCase(iter);
241         linkSlowCase(iter);
242     } else {
243         if (!supportsFloatingPoint()) {
244             if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
245                 linkSlowCase(iter); // int32 check
246             linkSlowCase(iter); // int32 check
247         } else {
248             if (!isOperandConstantImmediateInt(op1)) {
249                 linkSlowCase(iter); // double check
250                 linkSlowCase(iter); // int32 check
251             }
252             if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
253                 linkSlowCase(iter); // double check
254         }
255     }
256     JITStubCall stubCall(this, cti_op_jless);
257     stubCall.addArgument(op1);
258     stubCall.addArgument(op2);
259     stubCall.call();
260     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
261 }
262 
emit_op_jlesseq(Instruction * currentInstruction,bool invert)263 void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
264 {
265     unsigned op1 = currentInstruction[1].u.operand;
266     unsigned op2 = currentInstruction[2].u.operand;
267     unsigned target = currentInstruction[3].u.operand;
268 
269     JumpList notInt32Op1;
270     JumpList notInt32Op2;
271 
272     // Character less.
273     if (isOperandConstantImmediateChar(op1)) {
274         emitLoad(op2, regT1, regT0);
275         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
276         JumpList failures;
277         emitLoadCharacterString(regT0, regT0, failures);
278         addSlowCase(failures);
279         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
280         return;
281     }
282     if (isOperandConstantImmediateChar(op2)) {
283         emitLoad(op1, regT1, regT0);
284         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
285         JumpList failures;
286         emitLoadCharacterString(regT0, regT0, failures);
287         addSlowCase(failures);
288         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
289         return;
290     }
291     if (isOperandConstantImmediateInt(op1)) {
292         emitLoad(op2, regT3, regT2);
293         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
294         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
295     } else if (isOperandConstantImmediateInt(op2)) {
296         emitLoad(op1, regT1, regT0);
297         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
298         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
299     } else {
300         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
301         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
302         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
303         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT2), target);
304     }
305 
306     if (!supportsFloatingPoint()) {
307         addSlowCase(notInt32Op1);
308         addSlowCase(notInt32Op2);
309         return;
310     }
311     Jump end = jump();
312 
313     // Double less.
314     emitBinaryDoubleOp(invert ? op_jnlesseq : op_jlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
315     end.link(this);
316 }
317 
emitSlow_op_jlesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter,bool invert)318 void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert)
319 {
320     unsigned op1 = currentInstruction[1].u.operand;
321     unsigned op2 = currentInstruction[2].u.operand;
322     unsigned target = currentInstruction[3].u.operand;
323 
324     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
325         linkSlowCase(iter);
326         linkSlowCase(iter);
327         linkSlowCase(iter);
328         linkSlowCase(iter);
329     } else {
330         if (!supportsFloatingPoint()) {
331             if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
332                 linkSlowCase(iter); // int32 check
333             linkSlowCase(iter); // int32 check
334         } else {
335             if (!isOperandConstantImmediateInt(op1)) {
336                 linkSlowCase(iter); // double check
337                 linkSlowCase(iter); // int32 check
338             }
339             if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
340                 linkSlowCase(iter); // double check
341         }
342     }
343 
344     JITStubCall stubCall(this, cti_op_jlesseq);
345     stubCall.addArgument(op1);
346     stubCall.addArgument(op2);
347     stubCall.call();
348     emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
349 }
350 
emit_op_jnlesseq(Instruction * currentInstruction)351 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
352 {
353     emit_op_jlesseq(currentInstruction, true);
354 }
355 
emitSlow_op_jnlesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)356 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
357 {
358     emitSlow_op_jlesseq(currentInstruction, iter, true);
359 }
360 
361 // LeftShift (<<)
362 
emit_op_lshift(Instruction * currentInstruction)363 void JIT::emit_op_lshift(Instruction* currentInstruction)
364 {
365     unsigned dst = currentInstruction[1].u.operand;
366     unsigned op1 = currentInstruction[2].u.operand;
367     unsigned op2 = currentInstruction[3].u.operand;
368 
369     if (isOperandConstantImmediateInt(op2)) {
370         emitLoad(op1, regT1, regT0);
371         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
372         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
373         emitStoreInt32(dst, regT0, dst == op1);
374         return;
375     }
376 
377     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
378     if (!isOperandConstantImmediateInt(op1))
379         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
380     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
381     lshift32(regT2, regT0);
382     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
383 }
384 
emitSlow_op_lshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)385 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
386 {
387     unsigned dst = currentInstruction[1].u.operand;
388     unsigned op1 = currentInstruction[2].u.operand;
389     unsigned op2 = currentInstruction[3].u.operand;
390 
391     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
392         linkSlowCase(iter); // int32 check
393     linkSlowCase(iter); // int32 check
394 
395     JITStubCall stubCall(this, cti_op_lshift);
396     stubCall.addArgument(op1);
397     stubCall.addArgument(op2);
398     stubCall.call(dst);
399 }
400 
401 // RightShift (>>) and UnsignedRightShift (>>>) helper
402 
emitRightShift(Instruction * currentInstruction,bool isUnsigned)403 void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
404 {
405     unsigned dst = currentInstruction[1].u.operand;
406     unsigned op1 = currentInstruction[2].u.operand;
407     unsigned op2 = currentInstruction[3].u.operand;
408 
409     // Slow case of rshift makes assumptions about what registers hold the
410     // shift arguments, so any changes must be updated there as well.
411     if (isOperandConstantImmediateInt(op2)) {
412         emitLoad(op1, regT1, regT0);
413         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
414         int shift = getConstantOperand(op2).asInt32();
415         if (isUnsigned) {
416             if (shift)
417                 urshift32(Imm32(shift & 0x1f), regT0);
418             // unsigned shift < 0 or shift = k*2^32 may result in (essentially)
419             // a toUint conversion, which can result in a value we can represent
420             // as an immediate int.
421             if (shift < 0 || !(shift & 31))
422                 addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
423         } else if (shift) { // signed right shift by zero is simply toInt conversion
424             rshift32(Imm32(shift & 0x1f), regT0);
425         }
426         emitStoreInt32(dst, regT0, dst == op1);
427         return;
428     }
429 
430     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
431     if (!isOperandConstantImmediateInt(op1))
432         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
433     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
434     if (isUnsigned) {
435         urshift32(regT2, regT0);
436         addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
437     } else
438         rshift32(regT2, regT0);
439     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
440 }
441 
emitRightShiftSlowCase(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter,bool isUnsigned)442 void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned)
443 {
444     unsigned dst = currentInstruction[1].u.operand;
445     unsigned op1 = currentInstruction[2].u.operand;
446     unsigned op2 = currentInstruction[3].u.operand;
447     if (isOperandConstantImmediateInt(op2)) {
448         int shift = getConstantOperand(op2).asInt32();
449         // op1 = regT1:regT0
450         linkSlowCase(iter); // int32 check
451         if (supportsFloatingPointTruncate()) {
452             JumpList failures;
453             failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag)));
454             emitLoadDouble(op1, fpRegT0);
455             failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
456             if (isUnsigned) {
457                 if (shift)
458                     urshift32(Imm32(shift & 0x1f), regT0);
459                 if (shift < 0 || !(shift & 31))
460                     failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
461             } else if (shift)
462                 rshift32(Imm32(shift & 0x1f), regT0);
463             emitStoreInt32(dst, regT0, false);
464             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
465             failures.link(this);
466         }
467         if (isUnsigned && (shift < 0 || !(shift & 31)))
468             linkSlowCase(iter); // failed to box in hot path
469     } else {
470         // op1 = regT1:regT0
471         // op2 = regT3:regT2
472         if (!isOperandConstantImmediateInt(op1)) {
473             linkSlowCase(iter); // int32 check -- op1 is not an int
474             if (supportsFloatingPointTruncate()) {
475                 Jump notDouble = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)); // op1 is not a double
476                 emitLoadDouble(op1, fpRegT0);
477                 Jump notInt = branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)); // op2 is not an int
478                 Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0);
479                 if (isUnsigned)
480                     urshift32(regT2, regT0);
481                 else
482                     rshift32(regT2, regT0);
483                 emitStoreInt32(dst, regT0, false);
484                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
485                 notDouble.link(this);
486                 notInt.link(this);
487                 cantTruncate.link(this);
488             }
489         }
490 
491         linkSlowCase(iter); // int32 check - op2 is not an int
492         if (isUnsigned)
493             linkSlowCase(iter); // Can't represent unsigned result as an immediate
494     }
495 
496     JITStubCall stubCall(this, isUnsigned ? cti_op_urshift : cti_op_rshift);
497     stubCall.addArgument(op1);
498     stubCall.addArgument(op2);
499     stubCall.call(dst);
500 }
501 
502 // RightShift (>>)
503 
emit_op_rshift(Instruction * currentInstruction)504 void JIT::emit_op_rshift(Instruction* currentInstruction)
505 {
506     emitRightShift(currentInstruction, false);
507 }
508 
emitSlow_op_rshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)509 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
510 {
511     emitRightShiftSlowCase(currentInstruction, iter, false);
512 }
513 
514 // UnsignedRightShift (>>>)
515 
emit_op_urshift(Instruction * currentInstruction)516 void JIT::emit_op_urshift(Instruction* currentInstruction)
517 {
518     emitRightShift(currentInstruction, true);
519 }
520 
emitSlow_op_urshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)521 void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
522 {
523     emitRightShiftSlowCase(currentInstruction, iter, true);
524 }
525 
526 // BitAnd (&)
527 
emit_op_bitand(Instruction * currentInstruction)528 void JIT::emit_op_bitand(Instruction* currentInstruction)
529 {
530     unsigned dst = currentInstruction[1].u.operand;
531     unsigned op1 = currentInstruction[2].u.operand;
532     unsigned op2 = currentInstruction[3].u.operand;
533 
534     unsigned op;
535     int32_t constant;
536     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
537         emitLoad(op, regT1, regT0);
538         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
539         and32(Imm32(constant), regT0);
540         emitStoreInt32(dst, regT0, (op == dst));
541         return;
542     }
543 
544     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
545     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
546     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
547     and32(regT2, regT0);
548     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
549 }
550 
emitSlow_op_bitand(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)551 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
552 {
553     unsigned dst = currentInstruction[1].u.operand;
554     unsigned op1 = currentInstruction[2].u.operand;
555     unsigned op2 = currentInstruction[3].u.operand;
556 
557     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
558         linkSlowCase(iter); // int32 check
559     linkSlowCase(iter); // int32 check
560 
561     JITStubCall stubCall(this, cti_op_bitand);
562     stubCall.addArgument(op1);
563     stubCall.addArgument(op2);
564     stubCall.call(dst);
565 }
566 
567 // BitOr (|)
568 
emit_op_bitor(Instruction * currentInstruction)569 void JIT::emit_op_bitor(Instruction* currentInstruction)
570 {
571     unsigned dst = currentInstruction[1].u.operand;
572     unsigned op1 = currentInstruction[2].u.operand;
573     unsigned op2 = currentInstruction[3].u.operand;
574 
575     unsigned op;
576     int32_t constant;
577     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
578         emitLoad(op, regT1, regT0);
579         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
580         or32(Imm32(constant), regT0);
581         emitStoreInt32(dst, regT0, (op == dst));
582         return;
583     }
584 
585     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
586     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
587     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
588     or32(regT2, regT0);
589     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
590 }
591 
emitSlow_op_bitor(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)592 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
593 {
594     unsigned dst = currentInstruction[1].u.operand;
595     unsigned op1 = currentInstruction[2].u.operand;
596     unsigned op2 = currentInstruction[3].u.operand;
597 
598     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
599         linkSlowCase(iter); // int32 check
600     linkSlowCase(iter); // int32 check
601 
602     JITStubCall stubCall(this, cti_op_bitor);
603     stubCall.addArgument(op1);
604     stubCall.addArgument(op2);
605     stubCall.call(dst);
606 }
607 
608 // BitXor (^)
609 
emit_op_bitxor(Instruction * currentInstruction)610 void JIT::emit_op_bitxor(Instruction* currentInstruction)
611 {
612     unsigned dst = currentInstruction[1].u.operand;
613     unsigned op1 = currentInstruction[2].u.operand;
614     unsigned op2 = currentInstruction[3].u.operand;
615 
616     unsigned op;
617     int32_t constant;
618     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
619         emitLoad(op, regT1, regT0);
620         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
621         xor32(Imm32(constant), regT0);
622         emitStoreInt32(dst, regT0, (op == dst));
623         return;
624     }
625 
626     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
627     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
628     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
629     xor32(regT2, regT0);
630     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
631 }
632 
emitSlow_op_bitxor(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)633 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
634 {
635     unsigned dst = currentInstruction[1].u.operand;
636     unsigned op1 = currentInstruction[2].u.operand;
637     unsigned op2 = currentInstruction[3].u.operand;
638 
639     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
640         linkSlowCase(iter); // int32 check
641     linkSlowCase(iter); // int32 check
642 
643     JITStubCall stubCall(this, cti_op_bitxor);
644     stubCall.addArgument(op1);
645     stubCall.addArgument(op2);
646     stubCall.call(dst);
647 }
648 
649 // BitNot (~)
650 
emit_op_bitnot(Instruction * currentInstruction)651 void JIT::emit_op_bitnot(Instruction* currentInstruction)
652 {
653     unsigned dst = currentInstruction[1].u.operand;
654     unsigned src = currentInstruction[2].u.operand;
655 
656     emitLoad(src, regT1, regT0);
657     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
658 
659     not32(regT0);
660     emitStoreInt32(dst, regT0, (dst == src));
661 }
662 
emitSlow_op_bitnot(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)663 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
664 {
665     unsigned dst = currentInstruction[1].u.operand;
666 
667     linkSlowCase(iter); // int32 check
668 
669     JITStubCall stubCall(this, cti_op_bitnot);
670     stubCall.addArgument(regT1, regT0);
671     stubCall.call(dst);
672 }
673 
674 // PostInc (i++)
675 
emit_op_post_inc(Instruction * currentInstruction)676 void JIT::emit_op_post_inc(Instruction* currentInstruction)
677 {
678     unsigned dst = currentInstruction[1].u.operand;
679     unsigned srcDst = currentInstruction[2].u.operand;
680 
681     emitLoad(srcDst, regT1, regT0);
682     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
683 
684     if (dst == srcDst) // x = x++ is a noop for ints.
685         return;
686 
687     emitStoreInt32(dst, regT0);
688 
689     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
690     emitStoreInt32(srcDst, regT0, true);
691 }
692 
emitSlow_op_post_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)693 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
694 {
695     unsigned dst = currentInstruction[1].u.operand;
696     unsigned srcDst = currentInstruction[2].u.operand;
697 
698     linkSlowCase(iter); // int32 check
699     if (dst != srcDst)
700         linkSlowCase(iter); // overflow check
701 
702     JITStubCall stubCall(this, cti_op_post_inc);
703     stubCall.addArgument(srcDst);
704     stubCall.addArgument(Imm32(srcDst));
705     stubCall.call(dst);
706 }
707 
708 // PostDec (i--)
709 
emit_op_post_dec(Instruction * currentInstruction)710 void JIT::emit_op_post_dec(Instruction* currentInstruction)
711 {
712     unsigned dst = currentInstruction[1].u.operand;
713     unsigned srcDst = currentInstruction[2].u.operand;
714 
715     emitLoad(srcDst, regT1, regT0);
716     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
717 
718     if (dst == srcDst) // x = x-- is a noop for ints.
719         return;
720 
721     emitStoreInt32(dst, regT0);
722 
723     addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
724     emitStoreInt32(srcDst, regT0, true);
725 }
726 
emitSlow_op_post_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)727 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
728 {
729     unsigned dst = currentInstruction[1].u.operand;
730     unsigned srcDst = currentInstruction[2].u.operand;
731 
732     linkSlowCase(iter); // int32 check
733     if (dst != srcDst)
734         linkSlowCase(iter); // overflow check
735 
736     JITStubCall stubCall(this, cti_op_post_dec);
737     stubCall.addArgument(srcDst);
738     stubCall.addArgument(TrustedImm32(srcDst));
739     stubCall.call(dst);
740 }
741 
742 // PreInc (++i)
743 
emit_op_pre_inc(Instruction * currentInstruction)744 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
745 {
746     unsigned srcDst = currentInstruction[1].u.operand;
747 
748     emitLoad(srcDst, regT1, regT0);
749 
750     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
751     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
752     emitStoreInt32(srcDst, regT0, true);
753 }
754 
emitSlow_op_pre_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)755 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
756 {
757     unsigned srcDst = currentInstruction[1].u.operand;
758 
759     linkSlowCase(iter); // int32 check
760     linkSlowCase(iter); // overflow check
761 
762     JITStubCall stubCall(this, cti_op_pre_inc);
763     stubCall.addArgument(srcDst);
764     stubCall.call(srcDst);
765 }
766 
767 // PreDec (--i)
768 
emit_op_pre_dec(Instruction * currentInstruction)769 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
770 {
771     unsigned srcDst = currentInstruction[1].u.operand;
772 
773     emitLoad(srcDst, regT1, regT0);
774 
775     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
776     addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
777     emitStoreInt32(srcDst, regT0, true);
778 }
779 
emitSlow_op_pre_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)780 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
781 {
782     unsigned srcDst = currentInstruction[1].u.operand;
783 
784     linkSlowCase(iter); // int32 check
785     linkSlowCase(iter); // overflow check
786 
787     JITStubCall stubCall(this, cti_op_pre_dec);
788     stubCall.addArgument(srcDst);
789     stubCall.call(srcDst);
790 }
791 
792 // Addition (+)
793 
emit_op_add(Instruction * currentInstruction)794 void JIT::emit_op_add(Instruction* currentInstruction)
795 {
796     unsigned dst = currentInstruction[1].u.operand;
797     unsigned op1 = currentInstruction[2].u.operand;
798     unsigned op2 = currentInstruction[3].u.operand;
799     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
800 
801     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
802         JITStubCall stubCall(this, cti_op_add);
803         stubCall.addArgument(op1);
804         stubCall.addArgument(op2);
805         stubCall.call(dst);
806         return;
807     }
808 
809     JumpList notInt32Op1;
810     JumpList notInt32Op2;
811 
812     unsigned op;
813     int32_t constant;
814     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
815         emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second());
816         return;
817     }
818 
819     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
820     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
821     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
822 
823     // Int32 case.
824     addSlowCase(branchAdd32(Overflow, regT2, regT0));
825     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
826 
827     if (!supportsFloatingPoint()) {
828         addSlowCase(notInt32Op1);
829         addSlowCase(notInt32Op2);
830         return;
831     }
832     Jump end = jump();
833 
834     // Double case.
835     emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2);
836     end.link(this);
837 }
838 
emitAdd32Constant(unsigned dst,unsigned op,int32_t constant,ResultType opType)839 void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
840 {
841     // Int32 case.
842     emitLoad(op, regT1, regT0);
843     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
844     addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
845     emitStoreInt32(dst, regT0, (op == dst));
846 
847     // Double case.
848     if (!supportsFloatingPoint()) {
849         addSlowCase(notInt32);
850         return;
851     }
852     Jump end = jump();
853 
854     notInt32.link(this);
855     if (!opType.definitelyIsNumber())
856         addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
857     move(Imm32(constant), regT2);
858     convertInt32ToDouble(regT2, fpRegT0);
859     emitLoadDouble(op, fpRegT1);
860     addDouble(fpRegT1, fpRegT0);
861     emitStoreDouble(dst, fpRegT0);
862 
863     end.link(this);
864 }
865 
emitSlow_op_add(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)866 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
867 {
868     unsigned dst = currentInstruction[1].u.operand;
869     unsigned op1 = currentInstruction[2].u.operand;
870     unsigned op2 = currentInstruction[3].u.operand;
871     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
872 
873     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
874         return;
875 
876     unsigned op;
877     int32_t constant;
878     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
879         linkSlowCase(iter); // overflow check
880 
881         if (!supportsFloatingPoint())
882             linkSlowCase(iter); // non-sse case
883         else {
884             ResultType opType = op == op1 ? types.first() : types.second();
885             if (!opType.definitelyIsNumber())
886                 linkSlowCase(iter); // double check
887         }
888     } else {
889         linkSlowCase(iter); // overflow check
890 
891         if (!supportsFloatingPoint()) {
892             linkSlowCase(iter); // int32 check
893             linkSlowCase(iter); // int32 check
894         } else {
895             if (!types.first().definitelyIsNumber())
896                 linkSlowCase(iter); // double check
897 
898             if (!types.second().definitelyIsNumber()) {
899                 linkSlowCase(iter); // int32 check
900                 linkSlowCase(iter); // double check
901             }
902         }
903     }
904 
905     JITStubCall stubCall(this, cti_op_add);
906     stubCall.addArgument(op1);
907     stubCall.addArgument(op2);
908     stubCall.call(dst);
909 }
910 
911 // Subtraction (-)
912 
emit_op_sub(Instruction * currentInstruction)913 void JIT::emit_op_sub(Instruction* currentInstruction)
914 {
915     unsigned dst = currentInstruction[1].u.operand;
916     unsigned op1 = currentInstruction[2].u.operand;
917     unsigned op2 = currentInstruction[3].u.operand;
918     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
919 
920     JumpList notInt32Op1;
921     JumpList notInt32Op2;
922 
923     if (isOperandConstantImmediateInt(op2)) {
924         emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
925         return;
926     }
927 
928     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
929     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
930     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
931 
932     // Int32 case.
933     addSlowCase(branchSub32(Overflow, regT2, regT0));
934     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
935 
936     if (!supportsFloatingPoint()) {
937         addSlowCase(notInt32Op1);
938         addSlowCase(notInt32Op2);
939         return;
940     }
941     Jump end = jump();
942 
943     // Double case.
944     emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
945     end.link(this);
946 }
947 
emitSub32Constant(unsigned dst,unsigned op,int32_t constant,ResultType opType)948 void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
949 {
950     // Int32 case.
951     emitLoad(op, regT1, regT0);
952     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
953     addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
954     emitStoreInt32(dst, regT0, (op == dst));
955 
956     // Double case.
957     if (!supportsFloatingPoint()) {
958         addSlowCase(notInt32);
959         return;
960     }
961     Jump end = jump();
962 
963     notInt32.link(this);
964     if (!opType.definitelyIsNumber())
965         addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
966     move(Imm32(constant), regT2);
967     convertInt32ToDouble(regT2, fpRegT0);
968     emitLoadDouble(op, fpRegT1);
969     subDouble(fpRegT0, fpRegT1);
970     emitStoreDouble(dst, fpRegT1);
971 
972     end.link(this);
973 }
974 
emitSlow_op_sub(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)975 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
976 {
977     unsigned dst = currentInstruction[1].u.operand;
978     unsigned op1 = currentInstruction[2].u.operand;
979     unsigned op2 = currentInstruction[3].u.operand;
980     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
981 
982     if (isOperandConstantImmediateInt(op2)) {
983         linkSlowCase(iter); // overflow check
984 
985         if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
986             linkSlowCase(iter); // int32 or double check
987     } else {
988         linkSlowCase(iter); // overflow check
989 
990         if (!supportsFloatingPoint()) {
991             linkSlowCase(iter); // int32 check
992             linkSlowCase(iter); // int32 check
993         } else {
994             if (!types.first().definitelyIsNumber())
995                 linkSlowCase(iter); // double check
996 
997             if (!types.second().definitelyIsNumber()) {
998                 linkSlowCase(iter); // int32 check
999                 linkSlowCase(iter); // double check
1000             }
1001         }
1002     }
1003 
1004     JITStubCall stubCall(this, cti_op_sub);
1005     stubCall.addArgument(op1);
1006     stubCall.addArgument(op2);
1007     stubCall.call(dst);
1008 }
1009 
emitBinaryDoubleOp(OpcodeID opcodeID,unsigned dst,unsigned op1,unsigned op2,OperandTypes types,JumpList & notInt32Op1,JumpList & notInt32Op2,bool op1IsInRegisters,bool op2IsInRegisters)1010 void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
1011 {
1012     JumpList end;
1013 
1014     if (!notInt32Op1.empty()) {
1015         // Double case 1: Op1 is not int32; Op2 is unknown.
1016         notInt32Op1.link(this);
1017 
1018         ASSERT(op1IsInRegisters);
1019 
1020         // Verify Op1 is double.
1021         if (!types.first().definitelyIsNumber())
1022             addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
1023 
1024         if (!op2IsInRegisters)
1025             emitLoad(op2, regT3, regT2);
1026 
1027         Jump doubleOp2 = branch32(Below, regT3, TrustedImm32(JSValue::LowestTag));
1028 
1029         if (!types.second().definitelyIsNumber())
1030             addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
1031 
1032         convertInt32ToDouble(regT2, fpRegT0);
1033         Jump doTheMath = jump();
1034 
1035         // Load Op2 as double into double register.
1036         doubleOp2.link(this);
1037         emitLoadDouble(op2, fpRegT0);
1038 
1039         // Do the math.
1040         doTheMath.link(this);
1041         switch (opcodeID) {
1042             case op_mul:
1043                 emitLoadDouble(op1, fpRegT2);
1044                 mulDouble(fpRegT2, fpRegT0);
1045                 emitStoreDouble(dst, fpRegT0);
1046                 break;
1047             case op_add:
1048                 emitLoadDouble(op1, fpRegT2);
1049                 addDouble(fpRegT2, fpRegT0);
1050                 emitStoreDouble(dst, fpRegT0);
1051                 break;
1052             case op_sub:
1053                 emitLoadDouble(op1, fpRegT1);
1054                 subDouble(fpRegT0, fpRegT1);
1055                 emitStoreDouble(dst, fpRegT1);
1056                 break;
1057             case op_div:
1058                 emitLoadDouble(op1, fpRegT1);
1059                 divDouble(fpRegT0, fpRegT1);
1060                 emitStoreDouble(dst, fpRegT1);
1061                 break;
1062             case op_jnless:
1063                 emitLoadDouble(op1, fpRegT2);
1064                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
1065                 break;
1066             case op_jless:
1067                 emitLoadDouble(op1, fpRegT2);
1068                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
1069                 break;
1070             case op_jlesseq:
1071                 emitLoadDouble(op1, fpRegT2);
1072                 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst);
1073                 break;
1074             case op_jnlesseq:
1075                 emitLoadDouble(op1, fpRegT2);
1076                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
1077                 break;
1078             default:
1079                 ASSERT_NOT_REACHED();
1080         }
1081 
1082         if (!notInt32Op2.empty())
1083             end.append(jump());
1084     }
1085 
1086     if (!notInt32Op2.empty()) {
1087         // Double case 2: Op1 is int32; Op2 is not int32.
1088         notInt32Op2.link(this);
1089 
1090         ASSERT(op2IsInRegisters);
1091 
1092         if (!op1IsInRegisters)
1093             emitLoadPayload(op1, regT0);
1094 
1095         convertInt32ToDouble(regT0, fpRegT0);
1096 
1097         // Verify op2 is double.
1098         if (!types.second().definitelyIsNumber())
1099             addSlowCase(branch32(Above, regT3, TrustedImm32(JSValue::LowestTag)));
1100 
1101         // Do the math.
1102         switch (opcodeID) {
1103             case op_mul:
1104                 emitLoadDouble(op2, fpRegT2);
1105                 mulDouble(fpRegT2, fpRegT0);
1106                 emitStoreDouble(dst, fpRegT0);
1107                 break;
1108             case op_add:
1109                 emitLoadDouble(op2, fpRegT2);
1110                 addDouble(fpRegT2, fpRegT0);
1111                 emitStoreDouble(dst, fpRegT0);
1112                 break;
1113             case op_sub:
1114                 emitLoadDouble(op2, fpRegT2);
1115                 subDouble(fpRegT2, fpRegT0);
1116                 emitStoreDouble(dst, fpRegT0);
1117                 break;
1118             case op_div:
1119                 emitLoadDouble(op2, fpRegT2);
1120                 divDouble(fpRegT2, fpRegT0);
1121                 emitStoreDouble(dst, fpRegT0);
1122                 break;
1123             case op_jnless:
1124                 emitLoadDouble(op2, fpRegT1);
1125                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
1126                 break;
1127             case op_jless:
1128                 emitLoadDouble(op2, fpRegT1);
1129                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
1130                 break;
1131             case op_jnlesseq:
1132                 emitLoadDouble(op2, fpRegT1);
1133                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
1134                 break;
1135             case op_jlesseq:
1136                 emitLoadDouble(op2, fpRegT1);
1137                 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT1), dst);
1138                 break;
1139             default:
1140                 ASSERT_NOT_REACHED();
1141         }
1142     }
1143 
1144     end.link(this);
1145 }
1146 
1147 // Multiplication (*)
1148 
emit_op_mul(Instruction * currentInstruction)1149 void JIT::emit_op_mul(Instruction* currentInstruction)
1150 {
1151     unsigned dst = currentInstruction[1].u.operand;
1152     unsigned op1 = currentInstruction[2].u.operand;
1153     unsigned op2 = currentInstruction[3].u.operand;
1154     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1155 
1156     JumpList notInt32Op1;
1157     JumpList notInt32Op2;
1158 
1159     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1160     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
1161     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
1162 
1163     // Int32 case.
1164     move(regT0, regT3);
1165     addSlowCase(branchMul32(Overflow, regT2, regT0));
1166     addSlowCase(branchTest32(Zero, regT0));
1167     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1168 
1169     if (!supportsFloatingPoint()) {
1170         addSlowCase(notInt32Op1);
1171         addSlowCase(notInt32Op2);
1172         return;
1173     }
1174     Jump end = jump();
1175 
1176     // Double case.
1177     emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1178     end.link(this);
1179 }
1180 
emitSlow_op_mul(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1181 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1182 {
1183     unsigned dst = currentInstruction[1].u.operand;
1184     unsigned op1 = currentInstruction[2].u.operand;
1185     unsigned op2 = currentInstruction[3].u.operand;
1186     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1187 
1188     Jump overflow = getSlowCase(iter); // overflow check
1189     linkSlowCase(iter); // zero result check
1190 
1191     Jump negZero = branchOr32(Signed, regT2, regT3);
1192     emitStoreInt32(dst, TrustedImm32(0), (op1 == dst || op2 == dst));
1193 
1194     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
1195 
1196     negZero.link(this);
1197     overflow.link(this);
1198 
1199     if (!supportsFloatingPoint()) {
1200         linkSlowCase(iter); // int32 check
1201         linkSlowCase(iter); // int32 check
1202     }
1203 
1204     if (supportsFloatingPoint()) {
1205         if (!types.first().definitelyIsNumber())
1206             linkSlowCase(iter); // double check
1207 
1208         if (!types.second().definitelyIsNumber()) {
1209             linkSlowCase(iter); // int32 check
1210             linkSlowCase(iter); // double check
1211         }
1212     }
1213 
1214     Label jitStubCall(this);
1215     JITStubCall stubCall(this, cti_op_mul);
1216     stubCall.addArgument(op1);
1217     stubCall.addArgument(op2);
1218     stubCall.call(dst);
1219 }
1220 
1221 // Division (/)
1222 
emit_op_div(Instruction * currentInstruction)1223 void JIT::emit_op_div(Instruction* currentInstruction)
1224 {
1225     unsigned dst = currentInstruction[1].u.operand;
1226     unsigned op1 = currentInstruction[2].u.operand;
1227     unsigned op2 = currentInstruction[3].u.operand;
1228     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1229 
1230     if (!supportsFloatingPoint()) {
1231         addSlowCase(jump());
1232         return;
1233     }
1234 
1235     // Int32 divide.
1236     JumpList notInt32Op1;
1237     JumpList notInt32Op2;
1238 
1239     JumpList end;
1240 
1241     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1242 
1243     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
1244     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
1245 
1246     convertInt32ToDouble(regT0, fpRegT0);
1247     convertInt32ToDouble(regT2, fpRegT1);
1248     divDouble(fpRegT1, fpRegT0);
1249 
1250     JumpList doubleResult;
1251     branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1);
1252 
1253     // Int32 result.
1254     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1255     end.append(jump());
1256 
1257     // Double result.
1258     doubleResult.link(this);
1259     emitStoreDouble(dst, fpRegT0);
1260     end.append(jump());
1261 
1262     // Double divide.
1263     emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1264     end.link(this);
1265 }
1266 
emitSlow_op_div(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1267 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1268 {
1269     unsigned dst = currentInstruction[1].u.operand;
1270     unsigned op1 = currentInstruction[2].u.operand;
1271     unsigned op2 = currentInstruction[3].u.operand;
1272     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1273 
1274     if (!supportsFloatingPoint())
1275         linkSlowCase(iter);
1276     else {
1277         if (!types.first().definitelyIsNumber())
1278             linkSlowCase(iter); // double check
1279 
1280         if (!types.second().definitelyIsNumber()) {
1281             linkSlowCase(iter); // int32 check
1282             linkSlowCase(iter); // double check
1283         }
1284     }
1285 
1286     JITStubCall stubCall(this, cti_op_div);
1287     stubCall.addArgument(op1);
1288     stubCall.addArgument(op2);
1289     stubCall.call(dst);
1290 }
1291 
1292 // Mod (%)
1293 
1294 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
1295 
1296 #if CPU(X86) || CPU(X86_64) || CPU(MIPS)
1297 
emit_op_mod(Instruction * currentInstruction)1298 void JIT::emit_op_mod(Instruction* currentInstruction)
1299 {
1300     unsigned dst = currentInstruction[1].u.operand;
1301     unsigned op1 = currentInstruction[2].u.operand;
1302     unsigned op2 = currentInstruction[3].u.operand;
1303 
1304 #if CPU(X86) || CPU(X86_64)
1305     // Make sure registers are correct for x86 IDIV instructions.
1306     ASSERT(regT0 == X86Registers::eax);
1307     ASSERT(regT1 == X86Registers::edx);
1308     ASSERT(regT2 == X86Registers::ecx);
1309     ASSERT(regT3 == X86Registers::ebx);
1310 #endif
1311 
1312     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1313         emitLoad(op1, regT1, regT0);
1314         move(Imm32(getConstantOperand(op2).asInt32()), regT2);
1315         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
1316         if (getConstantOperand(op2).asInt32() == -1)
1317             addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1318     } else {
1319         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1320         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
1321         addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
1322 
1323         addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1324         addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); // divide by 0
1325     }
1326 
1327     move(regT0, regT3); // Save dividend payload, in case of 0.
1328 #if CPU(X86) || CPU(X86_64)
1329     m_assembler.cdq();
1330     m_assembler.idivl_r(regT2);
1331 #elif CPU(MIPS)
1332     m_assembler.div(regT0, regT2);
1333     m_assembler.mfhi(regT1);
1334 #endif
1335 
1336     // If the remainder is zero and the dividend is negative, the result is -0.
1337     Jump storeResult1 = branchTest32(NonZero, regT1);
1338     Jump storeResult2 = branchTest32(Zero, regT3, TrustedImm32(0x80000000)); // not negative
1339     emitStore(dst, jsNumber(-0.0));
1340     Jump end = jump();
1341 
1342     storeResult1.link(this);
1343     storeResult2.link(this);
1344     emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst));
1345     end.link(this);
1346 }
1347 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1348 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1349 {
1350     unsigned dst = currentInstruction[1].u.operand;
1351     unsigned op1 = currentInstruction[2].u.operand;
1352     unsigned op2 = currentInstruction[3].u.operand;
1353 
1354     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1355         linkSlowCase(iter); // int32 check
1356         if (getConstantOperand(op2).asInt32() == -1)
1357             linkSlowCase(iter); // 0x80000000 check
1358     } else {
1359         linkSlowCase(iter); // int32 check
1360         linkSlowCase(iter); // int32 check
1361         linkSlowCase(iter); // 0 check
1362         linkSlowCase(iter); // 0x80000000 check
1363     }
1364 
1365     JITStubCall stubCall(this, cti_op_mod);
1366     stubCall.addArgument(op1);
1367     stubCall.addArgument(op2);
1368     stubCall.call(dst);
1369 }
1370 
1371 #else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
1372 
emit_op_mod(Instruction * currentInstruction)1373 void JIT::emit_op_mod(Instruction* currentInstruction)
1374 {
1375     unsigned dst = currentInstruction[1].u.operand;
1376     unsigned op1 = currentInstruction[2].u.operand;
1377     unsigned op2 = currentInstruction[3].u.operand;
1378 
1379 #if ENABLE(JIT_USE_SOFT_MODULO)
1380     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1381     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
1382     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
1383 
1384     addSlowCase(branch32(Equal, regT2, TrustedImm32(0)));
1385 
1386     emitNakedCall(m_globalData->jitStubs->ctiSoftModulo());
1387 
1388     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1389 #else
1390     JITStubCall stubCall(this, cti_op_mod);
1391     stubCall.addArgument(op1);
1392     stubCall.addArgument(op2);
1393     stubCall.call(dst);
1394 #endif
1395 }
1396 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1397 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1398 {
1399     UNUSED_PARAM(currentInstruction);
1400     UNUSED_PARAM(iter);
1401 #if ENABLE(JIT_USE_SOFT_MODULO)
1402     unsigned result = currentInstruction[1].u.operand;
1403     unsigned op1 = currentInstruction[2].u.operand;
1404     unsigned op2 = currentInstruction[3].u.operand;
1405     linkSlowCase(iter);
1406     linkSlowCase(iter);
1407     linkSlowCase(iter);
1408     JITStubCall stubCall(this, cti_op_mod);
1409     stubCall.addArgument(op1);
1410     stubCall.addArgument(op2);
1411     stubCall.call(result);
1412 #else
1413     ASSERT_NOT_REACHED();
1414 #endif
1415 }
1416 
1417 #endif // CPU(X86) || CPU(X86_64)
1418 
1419 /* ------------------------------ END: OP_MOD ------------------------------ */
1420 
1421 } // namespace JSC
1422 
1423 #endif // USE(JSVALUE32_64)
1424 #endif // ENABLE(JIT)
1425