• 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 #include "JIT.h"
28 
29 #if ENABLE(JIT)
30 
31 #include "CodeBlock.h"
32 #include "JITInlineMethods.h"
33 #include "JITStubCall.h"
34 #include "JITStubs.h"
35 #include "JSArray.h"
36 #include "JSFunction.h"
37 #include "Interpreter.h"
38 #include "ResultType.h"
39 #include "SamplingTool.h"
40 
41 #ifndef NDEBUG
42 #include <stdio.h>
43 #endif
44 
45 using namespace std;
46 
47 namespace JSC {
48 
49 #if USE(JSVALUE32_64)
50 
emit_op_negate(Instruction * currentInstruction)51 void JIT::emit_op_negate(Instruction* currentInstruction)
52 {
53     unsigned dst = currentInstruction[1].u.operand;
54     unsigned src = currentInstruction[2].u.operand;
55 
56     emitLoad(src, regT1, regT0);
57 
58     Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
59     addSlowCase(branch32(Equal, regT0, Imm32(0)));
60 
61     neg32(regT0);
62     emitStoreInt32(dst, regT0, (dst == src));
63 
64     Jump end = jump();
65 
66     srcNotInt.link(this);
67     addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
68 
69     xor32(Imm32(1 << 31), regT1);
70     store32(regT1, tagFor(dst));
71     if (dst != src)
72         store32(regT0, payloadFor(dst));
73 
74     end.link(this);
75 }
76 
emitSlow_op_negate(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)77 void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
78 {
79     unsigned dst = currentInstruction[1].u.operand;
80 
81     linkSlowCase(iter); // 0 check
82     linkSlowCase(iter); // double check
83 
84     JITStubCall stubCall(this, cti_op_negate);
85     stubCall.addArgument(regT1, regT0);
86     stubCall.call(dst);
87 }
88 
emit_op_jnless(Instruction * currentInstruction)89 void JIT::emit_op_jnless(Instruction* currentInstruction)
90 {
91     unsigned op1 = currentInstruction[1].u.operand;
92     unsigned op2 = currentInstruction[2].u.operand;
93     unsigned target = currentInstruction[3].u.operand;
94 
95     JumpList notInt32Op1;
96     JumpList notInt32Op2;
97 
98     // Int32 less.
99     if (isOperandConstantImmediateInt(op1)) {
100         emitLoad(op2, regT3, regT2);
101         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
102         addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
103     } else if (isOperandConstantImmediateInt(op2)) {
104         emitLoad(op1, regT1, regT0);
105         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
106         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
107     } else {
108         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
109         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
110         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
111         addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
112     }
113 
114     if (!supportsFloatingPoint()) {
115         addSlowCase(notInt32Op1);
116         addSlowCase(notInt32Op2);
117         return;
118     }
119     Jump end = jump();
120 
121     // Double less.
122     emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
123     end.link(this);
124 }
125 
emitSlow_op_jnless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)126 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
127 {
128     unsigned op1 = currentInstruction[1].u.operand;
129     unsigned op2 = currentInstruction[2].u.operand;
130     unsigned target = currentInstruction[3].u.operand;
131 
132     if (!supportsFloatingPoint()) {
133         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
134             linkSlowCase(iter); // int32 check
135         linkSlowCase(iter); // int32 check
136     } else {
137         if (!isOperandConstantImmediateInt(op1)) {
138             linkSlowCase(iter); // double check
139             linkSlowCase(iter); // int32 check
140         }
141         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
142             linkSlowCase(iter); // double check
143     }
144 
145     JITStubCall stubCall(this, cti_op_jless);
146     stubCall.addArgument(op1);
147     stubCall.addArgument(op2);
148     stubCall.call();
149     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
150 }
151 
emit_op_jless(Instruction * currentInstruction)152 void JIT::emit_op_jless(Instruction* currentInstruction)
153 {
154     unsigned op1 = currentInstruction[1].u.operand;
155     unsigned op2 = currentInstruction[2].u.operand;
156     unsigned target = currentInstruction[3].u.operand;
157 
158     JumpList notInt32Op1;
159     JumpList notInt32Op2;
160 
161     // Int32 less.
162     if (isOperandConstantImmediateInt(op1)) {
163         emitLoad(op2, regT3, regT2);
164         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
165         addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
166     } else if (isOperandConstantImmediateInt(op2)) {
167         emitLoad(op1, regT1, regT0);
168         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
169         addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
170     } else {
171         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
172         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
173         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
174         addJump(branch32(LessThan, regT0, regT2), target);
175     }
176 
177     if (!supportsFloatingPoint()) {
178         addSlowCase(notInt32Op1);
179         addSlowCase(notInt32Op2);
180         return;
181     }
182     Jump end = jump();
183 
184     // Double less.
185     emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
186     end.link(this);
187 }
188 
emitSlow_op_jless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)189 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
190 {
191     unsigned op1 = currentInstruction[1].u.operand;
192     unsigned op2 = currentInstruction[2].u.operand;
193     unsigned target = currentInstruction[3].u.operand;
194 
195     if (!supportsFloatingPoint()) {
196         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
197             linkSlowCase(iter); // int32 check
198         linkSlowCase(iter); // int32 check
199     } else {
200         if (!isOperandConstantImmediateInt(op1)) {
201             linkSlowCase(iter); // double check
202             linkSlowCase(iter); // int32 check
203         }
204         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
205             linkSlowCase(iter); // double check
206     }
207 
208     JITStubCall stubCall(this, cti_op_jless);
209     stubCall.addArgument(op1);
210     stubCall.addArgument(op2);
211     stubCall.call();
212     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
213 }
214 
emit_op_jnlesseq(Instruction * currentInstruction)215 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
216 {
217     unsigned op1 = currentInstruction[1].u.operand;
218     unsigned op2 = currentInstruction[2].u.operand;
219     unsigned target = currentInstruction[3].u.operand;
220 
221     JumpList notInt32Op1;
222     JumpList notInt32Op2;
223 
224     // Int32 less.
225     if (isOperandConstantImmediateInt(op1)) {
226         emitLoad(op2, regT3, regT2);
227         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
228         addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
229     } else if (isOperandConstantImmediateInt(op2)) {
230         emitLoad(op1, regT1, regT0);
231         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
232         addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
233     } else {
234         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
235         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
236         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
237         addJump(branch32(GreaterThan, regT0, regT2), target);
238     }
239 
240     if (!supportsFloatingPoint()) {
241         addSlowCase(notInt32Op1);
242         addSlowCase(notInt32Op2);
243         return;
244     }
245     Jump end = jump();
246 
247     // Double less.
248     emitBinaryDoubleOp(op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
249     end.link(this);
250 }
251 
emitSlow_op_jnlesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)252 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
253 {
254     unsigned op1 = currentInstruction[1].u.operand;
255     unsigned op2 = currentInstruction[2].u.operand;
256     unsigned target = currentInstruction[3].u.operand;
257 
258     if (!supportsFloatingPoint()) {
259         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
260             linkSlowCase(iter); // int32 check
261         linkSlowCase(iter); // int32 check
262     } else {
263         if (!isOperandConstantImmediateInt(op1)) {
264             linkSlowCase(iter); // double check
265             linkSlowCase(iter); // int32 check
266         }
267         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
268             linkSlowCase(iter); // double check
269     }
270 
271     JITStubCall stubCall(this, cti_op_jlesseq);
272     stubCall.addArgument(op1);
273     stubCall.addArgument(op2);
274     stubCall.call();
275     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
276 }
277 
278 // LeftShift (<<)
279 
emit_op_lshift(Instruction * currentInstruction)280 void JIT::emit_op_lshift(Instruction* currentInstruction)
281 {
282     unsigned dst = currentInstruction[1].u.operand;
283     unsigned op1 = currentInstruction[2].u.operand;
284     unsigned op2 = currentInstruction[3].u.operand;
285 
286     if (isOperandConstantImmediateInt(op2)) {
287         emitLoad(op1, regT1, regT0);
288         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
289         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
290         emitStoreInt32(dst, regT0, dst == op1);
291         return;
292     }
293 
294     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
295     if (!isOperandConstantImmediateInt(op1))
296         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
297     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
298     lshift32(regT2, regT0);
299     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
300 }
301 
emitSlow_op_lshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)302 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
303 {
304     unsigned dst = currentInstruction[1].u.operand;
305     unsigned op1 = currentInstruction[2].u.operand;
306     unsigned op2 = currentInstruction[3].u.operand;
307 
308     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
309         linkSlowCase(iter); // int32 check
310     linkSlowCase(iter); // int32 check
311 
312     JITStubCall stubCall(this, cti_op_lshift);
313     stubCall.addArgument(op1);
314     stubCall.addArgument(op2);
315     stubCall.call(dst);
316 }
317 
318 // RightShift (>>)
319 
emit_op_rshift(Instruction * currentInstruction)320 void JIT::emit_op_rshift(Instruction* currentInstruction)
321 {
322     unsigned dst = currentInstruction[1].u.operand;
323     unsigned op1 = currentInstruction[2].u.operand;
324     unsigned op2 = currentInstruction[3].u.operand;
325 
326     if (isOperandConstantImmediateInt(op2)) {
327         emitLoad(op1, regT1, regT0);
328         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
329         rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
330         emitStoreInt32(dst, regT0, dst == op1);
331         return;
332     }
333 
334     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
335     if (!isOperandConstantImmediateInt(op1))
336         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
337     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
338     rshift32(regT2, regT0);
339     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
340 }
341 
emitSlow_op_rshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)342 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
343 {
344     unsigned dst = currentInstruction[1].u.operand;
345     unsigned op1 = currentInstruction[2].u.operand;
346     unsigned op2 = currentInstruction[3].u.operand;
347 
348     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
349         linkSlowCase(iter); // int32 check
350     linkSlowCase(iter); // int32 check
351 
352     JITStubCall stubCall(this, cti_op_rshift);
353     stubCall.addArgument(op1);
354     stubCall.addArgument(op2);
355     stubCall.call(dst);
356 }
357 
358 // BitAnd (&)
359 
emit_op_bitand(Instruction * currentInstruction)360 void JIT::emit_op_bitand(Instruction* currentInstruction)
361 {
362     unsigned dst = currentInstruction[1].u.operand;
363     unsigned op1 = currentInstruction[2].u.operand;
364     unsigned op2 = currentInstruction[3].u.operand;
365 
366     unsigned op;
367     int32_t constant;
368     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
369         emitLoad(op, regT1, regT0);
370         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
371         and32(Imm32(constant), regT0);
372         emitStoreInt32(dst, regT0, (op == dst));
373         return;
374     }
375 
376     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
377     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
378     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
379     and32(regT2, regT0);
380     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
381 }
382 
emitSlow_op_bitand(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)383 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
384 {
385     unsigned dst = currentInstruction[1].u.operand;
386     unsigned op1 = currentInstruction[2].u.operand;
387     unsigned op2 = currentInstruction[3].u.operand;
388 
389     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
390         linkSlowCase(iter); // int32 check
391     linkSlowCase(iter); // int32 check
392 
393     JITStubCall stubCall(this, cti_op_bitand);
394     stubCall.addArgument(op1);
395     stubCall.addArgument(op2);
396     stubCall.call(dst);
397 }
398 
399 // BitOr (|)
400 
emit_op_bitor(Instruction * currentInstruction)401 void JIT::emit_op_bitor(Instruction* currentInstruction)
402 {
403     unsigned dst = currentInstruction[1].u.operand;
404     unsigned op1 = currentInstruction[2].u.operand;
405     unsigned op2 = currentInstruction[3].u.operand;
406 
407     unsigned op;
408     int32_t constant;
409     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
410         emitLoad(op, regT1, regT0);
411         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
412         or32(Imm32(constant), regT0);
413         emitStoreInt32(dst, regT0, (op == dst));
414         return;
415     }
416 
417     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
418     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
419     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
420     or32(regT2, regT0);
421     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
422 }
423 
emitSlow_op_bitor(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)424 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
425 {
426     unsigned dst = currentInstruction[1].u.operand;
427     unsigned op1 = currentInstruction[2].u.operand;
428     unsigned op2 = currentInstruction[3].u.operand;
429 
430     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
431         linkSlowCase(iter); // int32 check
432     linkSlowCase(iter); // int32 check
433 
434     JITStubCall stubCall(this, cti_op_bitor);
435     stubCall.addArgument(op1);
436     stubCall.addArgument(op2);
437     stubCall.call(dst);
438 }
439 
440 // BitXor (^)
441 
emit_op_bitxor(Instruction * currentInstruction)442 void JIT::emit_op_bitxor(Instruction* currentInstruction)
443 {
444     unsigned dst = currentInstruction[1].u.operand;
445     unsigned op1 = currentInstruction[2].u.operand;
446     unsigned op2 = currentInstruction[3].u.operand;
447 
448     unsigned op;
449     int32_t constant;
450     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
451         emitLoad(op, regT1, regT0);
452         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
453         xor32(Imm32(constant), regT0);
454         emitStoreInt32(dst, regT0, (op == dst));
455         return;
456     }
457 
458     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
459     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
460     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
461     xor32(regT2, regT0);
462     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
463 }
464 
emitSlow_op_bitxor(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)465 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
466 {
467     unsigned dst = currentInstruction[1].u.operand;
468     unsigned op1 = currentInstruction[2].u.operand;
469     unsigned op2 = currentInstruction[3].u.operand;
470 
471     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
472         linkSlowCase(iter); // int32 check
473     linkSlowCase(iter); // int32 check
474 
475     JITStubCall stubCall(this, cti_op_bitxor);
476     stubCall.addArgument(op1);
477     stubCall.addArgument(op2);
478     stubCall.call(dst);
479 }
480 
481 // BitNot (~)
482 
emit_op_bitnot(Instruction * currentInstruction)483 void JIT::emit_op_bitnot(Instruction* currentInstruction)
484 {
485     unsigned dst = currentInstruction[1].u.operand;
486     unsigned src = currentInstruction[2].u.operand;
487 
488     emitLoad(src, regT1, regT0);
489     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
490 
491     not32(regT0);
492     emitStoreInt32(dst, regT0, (dst == src));
493 }
494 
emitSlow_op_bitnot(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)495 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
496 {
497     unsigned dst = currentInstruction[1].u.operand;
498 
499     linkSlowCase(iter); // int32 check
500 
501     JITStubCall stubCall(this, cti_op_bitnot);
502     stubCall.addArgument(regT1, regT0);
503     stubCall.call(dst);
504 }
505 
506 // PostInc (i++)
507 
emit_op_post_inc(Instruction * currentInstruction)508 void JIT::emit_op_post_inc(Instruction* currentInstruction)
509 {
510     unsigned dst = currentInstruction[1].u.operand;
511     unsigned srcDst = currentInstruction[2].u.operand;
512 
513     emitLoad(srcDst, regT1, regT0);
514     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
515 
516     if (dst == srcDst) // x = x++ is a noop for ints.
517         return;
518 
519     emitStoreInt32(dst, regT0);
520 
521     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
522     emitStoreInt32(srcDst, regT0, true);
523 }
524 
emitSlow_op_post_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)525 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
526 {
527     unsigned dst = currentInstruction[1].u.operand;
528     unsigned srcDst = currentInstruction[2].u.operand;
529 
530     linkSlowCase(iter); // int32 check
531     if (dst != srcDst)
532         linkSlowCase(iter); // overflow check
533 
534     JITStubCall stubCall(this, cti_op_post_inc);
535     stubCall.addArgument(srcDst);
536     stubCall.addArgument(Imm32(srcDst));
537     stubCall.call(dst);
538 }
539 
540 // PostDec (i--)
541 
emit_op_post_dec(Instruction * currentInstruction)542 void JIT::emit_op_post_dec(Instruction* currentInstruction)
543 {
544     unsigned dst = currentInstruction[1].u.operand;
545     unsigned srcDst = currentInstruction[2].u.operand;
546 
547     emitLoad(srcDst, regT1, regT0);
548     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
549 
550     if (dst == srcDst) // x = x-- is a noop for ints.
551         return;
552 
553     emitStoreInt32(dst, regT0);
554 
555     addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
556     emitStoreInt32(srcDst, regT0, true);
557 }
558 
emitSlow_op_post_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)559 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
560 {
561     unsigned dst = currentInstruction[1].u.operand;
562     unsigned srcDst = currentInstruction[2].u.operand;
563 
564     linkSlowCase(iter); // int32 check
565     if (dst != srcDst)
566         linkSlowCase(iter); // overflow check
567 
568     JITStubCall stubCall(this, cti_op_post_dec);
569     stubCall.addArgument(srcDst);
570     stubCall.addArgument(Imm32(srcDst));
571     stubCall.call(dst);
572 }
573 
574 // PreInc (++i)
575 
emit_op_pre_inc(Instruction * currentInstruction)576 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
577 {
578     unsigned srcDst = currentInstruction[1].u.operand;
579 
580     emitLoad(srcDst, regT1, regT0);
581 
582     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
583     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
584     emitStoreInt32(srcDst, regT0, true);
585 }
586 
emitSlow_op_pre_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)587 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
588 {
589     unsigned srcDst = currentInstruction[1].u.operand;
590 
591     linkSlowCase(iter); // int32 check
592     linkSlowCase(iter); // overflow check
593 
594     JITStubCall stubCall(this, cti_op_pre_inc);
595     stubCall.addArgument(srcDst);
596     stubCall.call(srcDst);
597 }
598 
599 // PreDec (--i)
600 
emit_op_pre_dec(Instruction * currentInstruction)601 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
602 {
603     unsigned srcDst = currentInstruction[1].u.operand;
604 
605     emitLoad(srcDst, regT1, regT0);
606 
607     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
608     addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
609     emitStoreInt32(srcDst, regT0, true);
610 }
611 
emitSlow_op_pre_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)612 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
613 {
614     unsigned srcDst = currentInstruction[1].u.operand;
615 
616     linkSlowCase(iter); // int32 check
617     linkSlowCase(iter); // overflow check
618 
619     JITStubCall stubCall(this, cti_op_pre_dec);
620     stubCall.addArgument(srcDst);
621     stubCall.call(srcDst);
622 }
623 
624 // Addition (+)
625 
emit_op_add(Instruction * currentInstruction)626 void JIT::emit_op_add(Instruction* currentInstruction)
627 {
628     unsigned dst = currentInstruction[1].u.operand;
629     unsigned op1 = currentInstruction[2].u.operand;
630     unsigned op2 = currentInstruction[3].u.operand;
631     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
632 
633     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
634         JITStubCall stubCall(this, cti_op_add);
635         stubCall.addArgument(op1);
636         stubCall.addArgument(op2);
637         stubCall.call(dst);
638         return;
639     }
640 
641     JumpList notInt32Op1;
642     JumpList notInt32Op2;
643 
644     unsigned op;
645     int32_t constant;
646     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
647         emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second());
648         return;
649     }
650 
651     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
652     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
653     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
654 
655     // Int32 case.
656     addSlowCase(branchAdd32(Overflow, regT2, regT0));
657     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
658 
659     if (!supportsFloatingPoint()) {
660         addSlowCase(notInt32Op1);
661         addSlowCase(notInt32Op2);
662         return;
663     }
664     Jump end = jump();
665 
666     // Double case.
667     emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2);
668     end.link(this);
669 }
670 
emitAdd32Constant(unsigned dst,unsigned op,int32_t constant,ResultType opType)671 void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
672 {
673     // Int32 case.
674     emitLoad(op, regT1, regT0);
675     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
676     addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
677     emitStoreInt32(dst, regT0, (op == dst));
678 
679     // Double case.
680     if (!supportsFloatingPoint()) {
681         addSlowCase(notInt32);
682         return;
683     }
684     Jump end = jump();
685 
686     notInt32.link(this);
687     if (!opType.definitelyIsNumber())
688         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
689     move(Imm32(constant), regT2);
690     convertInt32ToDouble(regT2, fpRegT0);
691     emitLoadDouble(op, fpRegT1);
692     addDouble(fpRegT1, fpRegT0);
693     emitStoreDouble(dst, fpRegT0);
694 
695     end.link(this);
696 }
697 
emitSlow_op_add(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)698 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
699 {
700     unsigned dst = currentInstruction[1].u.operand;
701     unsigned op1 = currentInstruction[2].u.operand;
702     unsigned op2 = currentInstruction[3].u.operand;
703     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
704 
705     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
706         return;
707 
708     unsigned op;
709     int32_t constant;
710     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
711         linkSlowCase(iter); // overflow check
712 
713         if (!supportsFloatingPoint())
714             linkSlowCase(iter); // non-sse case
715         else {
716             ResultType opType = op == op1 ? types.first() : types.second();
717             if (!opType.definitelyIsNumber())
718                 linkSlowCase(iter); // double check
719         }
720     } else {
721         linkSlowCase(iter); // overflow check
722 
723         if (!supportsFloatingPoint()) {
724             linkSlowCase(iter); // int32 check
725             linkSlowCase(iter); // int32 check
726         } else {
727             if (!types.first().definitelyIsNumber())
728                 linkSlowCase(iter); // double check
729 
730             if (!types.second().definitelyIsNumber()) {
731                 linkSlowCase(iter); // int32 check
732                 linkSlowCase(iter); // double check
733             }
734         }
735     }
736 
737     JITStubCall stubCall(this, cti_op_add);
738     stubCall.addArgument(op1);
739     stubCall.addArgument(op2);
740     stubCall.call(dst);
741 }
742 
743 // Subtraction (-)
744 
emit_op_sub(Instruction * currentInstruction)745 void JIT::emit_op_sub(Instruction* currentInstruction)
746 {
747     unsigned dst = currentInstruction[1].u.operand;
748     unsigned op1 = currentInstruction[2].u.operand;
749     unsigned op2 = currentInstruction[3].u.operand;
750     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
751 
752     JumpList notInt32Op1;
753     JumpList notInt32Op2;
754 
755     if (isOperandConstantImmediateInt(op2)) {
756         emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
757         return;
758     }
759 
760     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
761     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
762     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
763 
764     // Int32 case.
765     addSlowCase(branchSub32(Overflow, regT2, regT0));
766     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
767 
768     if (!supportsFloatingPoint()) {
769         addSlowCase(notInt32Op1);
770         addSlowCase(notInt32Op2);
771         return;
772     }
773     Jump end = jump();
774 
775     // Double case.
776     emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
777     end.link(this);
778 }
779 
emitSub32Constant(unsigned dst,unsigned op,int32_t constant,ResultType opType)780 void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
781 {
782     // Int32 case.
783     emitLoad(op, regT1, regT0);
784     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
785     addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
786     emitStoreInt32(dst, regT0, (op == dst));
787 
788     // Double case.
789     if (!supportsFloatingPoint()) {
790         addSlowCase(notInt32);
791         return;
792     }
793     Jump end = jump();
794 
795     notInt32.link(this);
796     if (!opType.definitelyIsNumber())
797         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
798     move(Imm32(constant), regT2);
799     convertInt32ToDouble(regT2, fpRegT0);
800     emitLoadDouble(op, fpRegT1);
801     subDouble(fpRegT0, fpRegT1);
802     emitStoreDouble(dst, fpRegT1);
803 
804     end.link(this);
805 }
806 
emitSlow_op_sub(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)807 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
808 {
809     unsigned dst = currentInstruction[1].u.operand;
810     unsigned op1 = currentInstruction[2].u.operand;
811     unsigned op2 = currentInstruction[3].u.operand;
812     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
813 
814     if (isOperandConstantImmediateInt(op2)) {
815         linkSlowCase(iter); // overflow check
816 
817         if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
818             linkSlowCase(iter); // int32 or double check
819     } else {
820         linkSlowCase(iter); // overflow check
821 
822         if (!supportsFloatingPoint()) {
823             linkSlowCase(iter); // int32 check
824             linkSlowCase(iter); // int32 check
825         } else {
826             if (!types.first().definitelyIsNumber())
827                 linkSlowCase(iter); // double check
828 
829             if (!types.second().definitelyIsNumber()) {
830                 linkSlowCase(iter); // int32 check
831                 linkSlowCase(iter); // double check
832             }
833         }
834     }
835 
836     JITStubCall stubCall(this, cti_op_sub);
837     stubCall.addArgument(op1);
838     stubCall.addArgument(op2);
839     stubCall.call(dst);
840 }
841 
emitBinaryDoubleOp(OpcodeID opcodeID,unsigned dst,unsigned op1,unsigned op2,OperandTypes types,JumpList & notInt32Op1,JumpList & notInt32Op2,bool op1IsInRegisters,bool op2IsInRegisters)842 void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
843 {
844     JumpList end;
845 
846     if (!notInt32Op1.empty()) {
847         // Double case 1: Op1 is not int32; Op2 is unknown.
848         notInt32Op1.link(this);
849 
850         ASSERT(op1IsInRegisters);
851 
852         // Verify Op1 is double.
853         if (!types.first().definitelyIsNumber())
854             addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
855 
856         if (!op2IsInRegisters)
857             emitLoad(op2, regT3, regT2);
858 
859         Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag));
860 
861         if (!types.second().definitelyIsNumber())
862             addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
863 
864         convertInt32ToDouble(regT2, fpRegT0);
865         Jump doTheMath = jump();
866 
867         // Load Op2 as double into double register.
868         doubleOp2.link(this);
869         emitLoadDouble(op2, fpRegT0);
870 
871         // Do the math.
872         doTheMath.link(this);
873         switch (opcodeID) {
874             case op_mul:
875                 emitLoadDouble(op1, fpRegT2);
876                 mulDouble(fpRegT2, fpRegT0);
877                 emitStoreDouble(dst, fpRegT0);
878                 break;
879             case op_add:
880                 emitLoadDouble(op1, fpRegT2);
881                 addDouble(fpRegT2, fpRegT0);
882                 emitStoreDouble(dst, fpRegT0);
883                 break;
884             case op_sub:
885                 emitLoadDouble(op1, fpRegT1);
886                 subDouble(fpRegT0, fpRegT1);
887                 emitStoreDouble(dst, fpRegT1);
888                 break;
889             case op_div:
890                 emitLoadDouble(op1, fpRegT1);
891                 divDouble(fpRegT0, fpRegT1);
892                 emitStoreDouble(dst, fpRegT1);
893                 break;
894             case op_jnless:
895                 emitLoadDouble(op1, fpRegT2);
896                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
897                 break;
898             case op_jless:
899                 emitLoadDouble(op1, fpRegT2);
900                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
901                 break;
902             case op_jnlesseq:
903                 emitLoadDouble(op1, fpRegT2);
904                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
905                 break;
906             default:
907                 ASSERT_NOT_REACHED();
908         }
909 
910         if (!notInt32Op2.empty())
911             end.append(jump());
912     }
913 
914     if (!notInt32Op2.empty()) {
915         // Double case 2: Op1 is int32; Op2 is not int32.
916         notInt32Op2.link(this);
917 
918         ASSERT(op2IsInRegisters);
919 
920         if (!op1IsInRegisters)
921             emitLoadPayload(op1, regT0);
922 
923         convertInt32ToDouble(regT0, fpRegT0);
924 
925         // Verify op2 is double.
926         if (!types.second().definitelyIsNumber())
927             addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag)));
928 
929         // Do the math.
930         switch (opcodeID) {
931             case op_mul:
932                 emitLoadDouble(op2, fpRegT2);
933                 mulDouble(fpRegT2, fpRegT0);
934                 emitStoreDouble(dst, fpRegT0);
935                 break;
936             case op_add:
937                 emitLoadDouble(op2, fpRegT2);
938                 addDouble(fpRegT2, fpRegT0);
939                 emitStoreDouble(dst, fpRegT0);
940                 break;
941             case op_sub:
942                 emitLoadDouble(op2, fpRegT2);
943                 subDouble(fpRegT2, fpRegT0);
944                 emitStoreDouble(dst, fpRegT0);
945                 break;
946             case op_div:
947                 emitLoadDouble(op2, fpRegT2);
948                 divDouble(fpRegT2, fpRegT0);
949                 emitStoreDouble(dst, fpRegT0);
950                 break;
951             case op_jnless:
952                 emitLoadDouble(op2, fpRegT1);
953                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
954                 break;
955             case op_jless:
956                 emitLoadDouble(op2, fpRegT1);
957                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
958                 break;
959             case op_jnlesseq:
960                 emitLoadDouble(op2, fpRegT1);
961                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
962                 break;
963             default:
964                 ASSERT_NOT_REACHED();
965         }
966     }
967 
968     end.link(this);
969 }
970 
971 // Multiplication (*)
972 
emit_op_mul(Instruction * currentInstruction)973 void JIT::emit_op_mul(Instruction* currentInstruction)
974 {
975     unsigned dst = currentInstruction[1].u.operand;
976     unsigned op1 = currentInstruction[2].u.operand;
977     unsigned op2 = currentInstruction[3].u.operand;
978     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
979 
980     JumpList notInt32Op1;
981     JumpList notInt32Op2;
982 
983     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
984     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
985     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
986 
987     // Int32 case.
988     move(regT0, regT3);
989     addSlowCase(branchMul32(Overflow, regT2, regT0));
990     addSlowCase(branchTest32(Zero, regT0));
991     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
992 
993     if (!supportsFloatingPoint()) {
994         addSlowCase(notInt32Op1);
995         addSlowCase(notInt32Op2);
996         return;
997     }
998     Jump end = jump();
999 
1000     // Double case.
1001     emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1002     end.link(this);
1003 }
1004 
emitSlow_op_mul(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1005 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1006 {
1007     unsigned dst = currentInstruction[1].u.operand;
1008     unsigned op1 = currentInstruction[2].u.operand;
1009     unsigned op2 = currentInstruction[3].u.operand;
1010     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1011 
1012     Jump overflow = getSlowCase(iter); // overflow check
1013     linkSlowCase(iter); // zero result check
1014 
1015     Jump negZero = branchOr32(Signed, regT2, regT3);
1016     emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst));
1017 
1018     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
1019 
1020     negZero.link(this);
1021     overflow.link(this);
1022 
1023     if (!supportsFloatingPoint()) {
1024         linkSlowCase(iter); // int32 check
1025         linkSlowCase(iter); // int32 check
1026     }
1027 
1028     if (supportsFloatingPoint()) {
1029         if (!types.first().definitelyIsNumber())
1030             linkSlowCase(iter); // double check
1031 
1032         if (!types.second().definitelyIsNumber()) {
1033             linkSlowCase(iter); // int32 check
1034             linkSlowCase(iter); // double check
1035         }
1036     }
1037 
1038     Label jitStubCall(this);
1039     JITStubCall stubCall(this, cti_op_mul);
1040     stubCall.addArgument(op1);
1041     stubCall.addArgument(op2);
1042     stubCall.call(dst);
1043 }
1044 
1045 // Division (/)
1046 
emit_op_div(Instruction * currentInstruction)1047 void JIT::emit_op_div(Instruction* currentInstruction)
1048 {
1049     unsigned dst = currentInstruction[1].u.operand;
1050     unsigned op1 = currentInstruction[2].u.operand;
1051     unsigned op2 = currentInstruction[3].u.operand;
1052     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1053 
1054     if (!supportsFloatingPoint()) {
1055         addSlowCase(jump());
1056         return;
1057     }
1058 
1059     // Int32 divide.
1060     JumpList notInt32Op1;
1061     JumpList notInt32Op2;
1062 
1063     JumpList end;
1064 
1065     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1066 
1067     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
1068     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
1069 
1070     convertInt32ToDouble(regT0, fpRegT0);
1071     convertInt32ToDouble(regT2, fpRegT1);
1072     divDouble(fpRegT1, fpRegT0);
1073 
1074     JumpList doubleResult;
1075     branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1);
1076 
1077     // Int32 result.
1078     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1079     end.append(jump());
1080 
1081     // Double result.
1082     doubleResult.link(this);
1083     emitStoreDouble(dst, fpRegT0);
1084     end.append(jump());
1085 
1086     // Double divide.
1087     emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1088     end.link(this);
1089 }
1090 
emitSlow_op_div(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1091 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1092 {
1093     unsigned dst = currentInstruction[1].u.operand;
1094     unsigned op1 = currentInstruction[2].u.operand;
1095     unsigned op2 = currentInstruction[3].u.operand;
1096     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1097 
1098     if (!supportsFloatingPoint())
1099         linkSlowCase(iter);
1100     else {
1101         if (!types.first().definitelyIsNumber())
1102             linkSlowCase(iter); // double check
1103 
1104         if (!types.second().definitelyIsNumber()) {
1105             linkSlowCase(iter); // int32 check
1106             linkSlowCase(iter); // double check
1107         }
1108     }
1109 
1110     JITStubCall stubCall(this, cti_op_div);
1111     stubCall.addArgument(op1);
1112     stubCall.addArgument(op2);
1113     stubCall.call(dst);
1114 }
1115 
1116 // Mod (%)
1117 
1118 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
1119 
1120 #if CPU(X86) || CPU(X86_64)
1121 
emit_op_mod(Instruction * currentInstruction)1122 void JIT::emit_op_mod(Instruction* currentInstruction)
1123 {
1124     unsigned dst = currentInstruction[1].u.operand;
1125     unsigned op1 = currentInstruction[2].u.operand;
1126     unsigned op2 = currentInstruction[3].u.operand;
1127 
1128     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1129         emitLoad(op1, X86Registers::edx, X86Registers::eax);
1130         move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx);
1131         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
1132         if (getConstantOperand(op2).asInt32() == -1)
1133             addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1134     } else {
1135         emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx);
1136         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
1137         addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag)));
1138 
1139         addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1140         addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0
1141     }
1142 
1143     move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0.
1144     m_assembler.cdq();
1145     m_assembler.idivl_r(X86Registers::ecx);
1146 
1147     // If the remainder is zero and the dividend is negative, the result is -0.
1148     Jump storeResult1 = branchTest32(NonZero, X86Registers::edx);
1149     Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative
1150     emitStore(dst, jsNumber(m_globalData, -0.0));
1151     Jump end = jump();
1152 
1153     storeResult1.link(this);
1154     storeResult2.link(this);
1155     emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst));
1156     end.link(this);
1157 }
1158 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1159 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1160 {
1161     unsigned dst = currentInstruction[1].u.operand;
1162     unsigned op1 = currentInstruction[2].u.operand;
1163     unsigned op2 = currentInstruction[3].u.operand;
1164 
1165     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1166         linkSlowCase(iter); // int32 check
1167         if (getConstantOperand(op2).asInt32() == -1)
1168             linkSlowCase(iter); // 0x80000000 check
1169     } else {
1170         linkSlowCase(iter); // int32 check
1171         linkSlowCase(iter); // int32 check
1172         linkSlowCase(iter); // 0 check
1173         linkSlowCase(iter); // 0x80000000 check
1174     }
1175 
1176     JITStubCall stubCall(this, cti_op_mod);
1177     stubCall.addArgument(op1);
1178     stubCall.addArgument(op2);
1179     stubCall.call(dst);
1180 }
1181 
1182 #else // CPU(X86) || CPU(X86_64)
1183 
emit_op_mod(Instruction * currentInstruction)1184 void JIT::emit_op_mod(Instruction* currentInstruction)
1185 {
1186     unsigned dst = currentInstruction[1].u.operand;
1187     unsigned op1 = currentInstruction[2].u.operand;
1188     unsigned op2 = currentInstruction[3].u.operand;
1189 
1190 #if ENABLE(JIT_OPTIMIZE_MOD)
1191     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1192     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
1193     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
1194 
1195     addSlowCase(branch32(Equal, regT2, Imm32(0)));
1196 
1197     emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
1198 
1199     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1200 #else
1201     JITStubCall stubCall(this, cti_op_mod);
1202     stubCall.addArgument(op1);
1203     stubCall.addArgument(op2);
1204     stubCall.call(dst);
1205 #endif
1206 }
1207 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1208 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1209 {
1210 #if ENABLE(JIT_OPTIMIZE_MOD)
1211     unsigned result = currentInstruction[1].u.operand;
1212     unsigned op1 = currentInstruction[2].u.operand;
1213     unsigned op2 = currentInstruction[3].u.operand;
1214     linkSlowCase(iter);
1215     linkSlowCase(iter);
1216     linkSlowCase(iter);
1217     JITStubCall stubCall(this, cti_op_mod);
1218     stubCall.addArgument(op1);
1219     stubCall.addArgument(op2);
1220     stubCall.call(result);
1221 #else
1222     ASSERT_NOT_REACHED();
1223 #endif
1224 }
1225 
1226 #endif // CPU(X86) || CPU(X86_64)
1227 
1228 /* ------------------------------ END: OP_MOD ------------------------------ */
1229 
1230 #else // USE(JSVALUE32_64)
1231 
1232 void JIT::emit_op_lshift(Instruction* currentInstruction)
1233 {
1234     unsigned result = currentInstruction[1].u.operand;
1235     unsigned op1 = currentInstruction[2].u.operand;
1236     unsigned op2 = currentInstruction[3].u.operand;
1237 
1238     emitGetVirtualRegisters(op1, regT0, op2, regT2);
1239     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
1240     emitJumpSlowCaseIfNotImmediateInteger(regT0);
1241     emitJumpSlowCaseIfNotImmediateInteger(regT2);
1242     emitFastArithImmToInt(regT0);
1243     emitFastArithImmToInt(regT2);
1244     lshift32(regT2, regT0);
1245 #if USE(JSVALUE32)
1246     addSlowCase(branchAdd32(Overflow, regT0, regT0));
1247     signExtend32ToPtr(regT0, regT0);
1248 #endif
1249     emitFastArithReTagImmediate(regT0, regT0);
1250     emitPutVirtualRegister(result);
1251 }
1252 
1253 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1254 {
1255     unsigned result = currentInstruction[1].u.operand;
1256     unsigned op1 = currentInstruction[2].u.operand;
1257     unsigned op2 = currentInstruction[3].u.operand;
1258 
1259 #if USE(JSVALUE64)
1260     UNUSED_PARAM(op1);
1261     UNUSED_PARAM(op2);
1262     linkSlowCase(iter);
1263     linkSlowCase(iter);
1264 #else
1265     // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
1266     Jump notImm1 = getSlowCase(iter);
1267     Jump notImm2 = getSlowCase(iter);
1268     linkSlowCase(iter);
1269     emitGetVirtualRegisters(op1, regT0, op2, regT2);
1270     notImm1.link(this);
1271     notImm2.link(this);
1272 #endif
1273     JITStubCall stubCall(this, cti_op_lshift);
1274     stubCall.addArgument(regT0);
1275     stubCall.addArgument(regT2);
1276     stubCall.call(result);
1277 }
1278 
1279 void JIT::emit_op_rshift(Instruction* currentInstruction)
1280 {
1281     unsigned result = currentInstruction[1].u.operand;
1282     unsigned op1 = currentInstruction[2].u.operand;
1283     unsigned op2 = currentInstruction[3].u.operand;
1284 
1285     if (isOperandConstantImmediateInt(op2)) {
1286         // isOperandConstantImmediateInt(op2) => 1 SlowCase
1287         emitGetVirtualRegister(op1, regT0);
1288         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1289         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
1290         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
1291     } else {
1292         emitGetVirtualRegisters(op1, regT0, op2, regT2);
1293         if (supportsFloatingPointTruncate()) {
1294             Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
1295 #if USE(JSVALUE64)
1296             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
1297             addSlowCase(emitJumpIfNotImmediateNumber(regT0));
1298             addPtr(tagTypeNumberRegister, regT0);
1299             movePtrToDouble(regT0, fpRegT0);
1300             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
1301 #else
1302             // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell)
1303             emitJumpSlowCaseIfNotJSCell(regT0, op1);
1304             addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get()));
1305             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1306             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
1307             addSlowCase(branchAdd32(Overflow, regT0, regT0));
1308 #endif
1309             lhsIsInt.link(this);
1310             emitJumpSlowCaseIfNotImmediateInteger(regT2);
1311         } else {
1312             // !supportsFloatingPoint() => 2 SlowCases
1313             emitJumpSlowCaseIfNotImmediateInteger(regT0);
1314             emitJumpSlowCaseIfNotImmediateInteger(regT2);
1315         }
1316         emitFastArithImmToInt(regT2);
1317         rshift32(regT2, regT0);
1318 #if USE(JSVALUE32)
1319         signExtend32ToPtr(regT0, regT0);
1320 #endif
1321     }
1322 #if USE(JSVALUE64)
1323     emitFastArithIntToImmNoCheck(regT0, regT0);
1324 #else
1325     orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
1326 #endif
1327     emitPutVirtualRegister(result);
1328 }
1329 
1330 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1331 {
1332     unsigned result = currentInstruction[1].u.operand;
1333     unsigned op1 = currentInstruction[2].u.operand;
1334     unsigned op2 = currentInstruction[3].u.operand;
1335 
1336     JITStubCall stubCall(this, cti_op_rshift);
1337 
1338     if (isOperandConstantImmediateInt(op2)) {
1339         linkSlowCase(iter);
1340         stubCall.addArgument(regT0);
1341         stubCall.addArgument(op2, regT2);
1342     } else {
1343         if (supportsFloatingPointTruncate()) {
1344 #if USE(JSVALUE64)
1345             linkSlowCase(iter);
1346             linkSlowCase(iter);
1347             linkSlowCase(iter);
1348 #else
1349             linkSlowCaseIfNotJSCell(iter, op1);
1350             linkSlowCase(iter);
1351             linkSlowCase(iter);
1352             linkSlowCase(iter);
1353             linkSlowCase(iter);
1354 #endif
1355             // We're reloading op1 to regT0 as we can no longer guarantee that
1356             // we have not munged the operand.  It may have already been shifted
1357             // correctly, but it still will not have been tagged.
1358             stubCall.addArgument(op1, regT0);
1359             stubCall.addArgument(regT2);
1360         } else {
1361             linkSlowCase(iter);
1362             linkSlowCase(iter);
1363             stubCall.addArgument(regT0);
1364             stubCall.addArgument(regT2);
1365         }
1366     }
1367 
1368     stubCall.call(result);
1369 }
1370 
1371 void JIT::emit_op_jnless(Instruction* currentInstruction)
1372 {
1373     unsigned op1 = currentInstruction[1].u.operand;
1374     unsigned op2 = currentInstruction[2].u.operand;
1375     unsigned target = currentInstruction[3].u.operand;
1376 
1377     // We generate inline code for the following cases in the fast path:
1378     // - int immediate to constant int immediate
1379     // - constant int immediate to int immediate
1380     // - int immediate to int immediate
1381 
1382     if (isOperandConstantImmediateInt(op2)) {
1383         emitGetVirtualRegister(op1, regT0);
1384         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1385 #if USE(JSVALUE64)
1386         int32_t op2imm = getConstantOperandImmediateInt(op2);
1387 #else
1388         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1389 #endif
1390         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
1391     } else if (isOperandConstantImmediateInt(op1)) {
1392         emitGetVirtualRegister(op2, regT1);
1393         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1394 #if USE(JSVALUE64)
1395         int32_t op1imm = getConstantOperandImmediateInt(op1);
1396 #else
1397         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1398 #endif
1399         addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
1400     } else {
1401         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1402         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1403         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1404 
1405         addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
1406     }
1407 }
1408 
1409 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1410 {
1411     unsigned op1 = currentInstruction[1].u.operand;
1412     unsigned op2 = currentInstruction[2].u.operand;
1413     unsigned target = currentInstruction[3].u.operand;
1414 
1415     // We generate inline code for the following cases in the slow path:
1416     // - floating-point number to constant int immediate
1417     // - constant int immediate to floating-point number
1418     // - floating-point number to floating-point number.
1419 
1420     if (isOperandConstantImmediateInt(op2)) {
1421         linkSlowCase(iter);
1422 
1423         if (supportsFloatingPoint()) {
1424 #if USE(JSVALUE64)
1425             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1426             addPtr(tagTypeNumberRegister, regT0);
1427             movePtrToDouble(regT0, fpRegT0);
1428 #else
1429             Jump fail1;
1430             if (!m_codeBlock->isKnownNotImmediate(op1))
1431                 fail1 = emitJumpIfNotJSCell(regT0);
1432 
1433             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1434             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1435 #endif
1436 
1437             int32_t op2imm = getConstantOperand(op2).asInt32();;
1438 
1439             move(Imm32(op2imm), regT1);
1440             convertInt32ToDouble(regT1, fpRegT1);
1441 
1442             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1443 
1444             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1445 
1446 #if USE(JSVALUE64)
1447             fail1.link(this);
1448 #else
1449             if (!m_codeBlock->isKnownNotImmediate(op1))
1450                 fail1.link(this);
1451             fail2.link(this);
1452 #endif
1453         }
1454 
1455         JITStubCall stubCall(this, cti_op_jless);
1456         stubCall.addArgument(regT0);
1457         stubCall.addArgument(op2, regT2);
1458         stubCall.call();
1459         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1460 
1461     } else if (isOperandConstantImmediateInt(op1)) {
1462         linkSlowCase(iter);
1463 
1464         if (supportsFloatingPoint()) {
1465 #if USE(JSVALUE64)
1466             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1467             addPtr(tagTypeNumberRegister, regT1);
1468             movePtrToDouble(regT1, fpRegT1);
1469 #else
1470             Jump fail1;
1471             if (!m_codeBlock->isKnownNotImmediate(op2))
1472                 fail1 = emitJumpIfNotJSCell(regT1);
1473 
1474             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1475             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1476 #endif
1477 
1478             int32_t op1imm = getConstantOperand(op1).asInt32();;
1479 
1480             move(Imm32(op1imm), regT0);
1481             convertInt32ToDouble(regT0, fpRegT0);
1482 
1483             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1484 
1485             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1486 
1487 #if USE(JSVALUE64)
1488             fail1.link(this);
1489 #else
1490             if (!m_codeBlock->isKnownNotImmediate(op2))
1491                 fail1.link(this);
1492             fail2.link(this);
1493 #endif
1494         }
1495 
1496         JITStubCall stubCall(this, cti_op_jless);
1497         stubCall.addArgument(op1, regT2);
1498         stubCall.addArgument(regT1);
1499         stubCall.call();
1500         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1501 
1502     } else {
1503         linkSlowCase(iter);
1504 
1505         if (supportsFloatingPoint()) {
1506 #if USE(JSVALUE64)
1507             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1508             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1509             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1510             addPtr(tagTypeNumberRegister, regT0);
1511             addPtr(tagTypeNumberRegister, regT1);
1512             movePtrToDouble(regT0, fpRegT0);
1513             movePtrToDouble(regT1, fpRegT1);
1514 #else
1515             Jump fail1;
1516             if (!m_codeBlock->isKnownNotImmediate(op1))
1517                 fail1 = emitJumpIfNotJSCell(regT0);
1518 
1519             Jump fail2;
1520             if (!m_codeBlock->isKnownNotImmediate(op2))
1521                 fail2 = emitJumpIfNotJSCell(regT1);
1522 
1523             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1524             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1525             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1526             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1527 #endif
1528 
1529             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1530 
1531             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1532 
1533 #if USE(JSVALUE64)
1534             fail1.link(this);
1535             fail2.link(this);
1536             fail3.link(this);
1537 #else
1538             if (!m_codeBlock->isKnownNotImmediate(op1))
1539                 fail1.link(this);
1540             if (!m_codeBlock->isKnownNotImmediate(op2))
1541                 fail2.link(this);
1542             fail3.link(this);
1543             fail4.link(this);
1544 #endif
1545         }
1546 
1547         linkSlowCase(iter);
1548         JITStubCall stubCall(this, cti_op_jless);
1549         stubCall.addArgument(regT0);
1550         stubCall.addArgument(regT1);
1551         stubCall.call();
1552         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1553     }
1554 }
1555 
1556 void JIT::emit_op_jless(Instruction* currentInstruction)
1557 {
1558     unsigned op1 = currentInstruction[1].u.operand;
1559     unsigned op2 = currentInstruction[2].u.operand;
1560     unsigned target = currentInstruction[3].u.operand;
1561 
1562     // We generate inline code for the following cases in the fast path:
1563     // - int immediate to constant int immediate
1564     // - constant int immediate to int immediate
1565     // - int immediate to int immediate
1566 
1567     if (isOperandConstantImmediateInt(op2)) {
1568         emitGetVirtualRegister(op1, regT0);
1569         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1570 #if USE(JSVALUE64)
1571         int32_t op2imm = getConstantOperandImmediateInt(op2);
1572 #else
1573         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1574 #endif
1575         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
1576     } else if (isOperandConstantImmediateInt(op1)) {
1577         emitGetVirtualRegister(op2, regT1);
1578         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1579 #if USE(JSVALUE64)
1580         int32_t op1imm = getConstantOperandImmediateInt(op1);
1581 #else
1582         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1583 #endif
1584         addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
1585     } else {
1586         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1587         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1588         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1589 
1590         addJump(branch32(LessThan, regT0, regT1), target);
1591     }
1592 }
1593 
1594 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1595 {
1596     unsigned op1 = currentInstruction[1].u.operand;
1597     unsigned op2 = currentInstruction[2].u.operand;
1598     unsigned target = currentInstruction[3].u.operand;
1599 
1600     // We generate inline code for the following cases in the slow path:
1601     // - floating-point number to constant int immediate
1602     // - constant int immediate to floating-point number
1603     // - floating-point number to floating-point number.
1604 
1605     if (isOperandConstantImmediateInt(op2)) {
1606         linkSlowCase(iter);
1607 
1608         if (supportsFloatingPoint()) {
1609 #if USE(JSVALUE64)
1610             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1611             addPtr(tagTypeNumberRegister, regT0);
1612             movePtrToDouble(regT0, fpRegT0);
1613 #else
1614             Jump fail1;
1615             if (!m_codeBlock->isKnownNotImmediate(op1))
1616                 fail1 = emitJumpIfNotJSCell(regT0);
1617 
1618             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1619             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1620 #endif
1621 
1622             int32_t op2imm = getConstantOperand(op2).asInt32();
1623 
1624             move(Imm32(op2imm), regT1);
1625             convertInt32ToDouble(regT1, fpRegT1);
1626 
1627             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1628 
1629             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1630 
1631 #if USE(JSVALUE64)
1632             fail1.link(this);
1633 #else
1634             if (!m_codeBlock->isKnownNotImmediate(op1))
1635                 fail1.link(this);
1636             fail2.link(this);
1637 #endif
1638         }
1639 
1640         JITStubCall stubCall(this, cti_op_jless);
1641         stubCall.addArgument(regT0);
1642         stubCall.addArgument(op2, regT2);
1643         stubCall.call();
1644         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
1645 
1646     } else if (isOperandConstantImmediateInt(op1)) {
1647         linkSlowCase(iter);
1648 
1649         if (supportsFloatingPoint()) {
1650 #if USE(JSVALUE64)
1651             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1652             addPtr(tagTypeNumberRegister, regT1);
1653             movePtrToDouble(regT1, fpRegT1);
1654 #else
1655             Jump fail1;
1656             if (!m_codeBlock->isKnownNotImmediate(op2))
1657                 fail1 = emitJumpIfNotJSCell(regT1);
1658 
1659             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1660             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1661 #endif
1662 
1663             int32_t op1imm = getConstantOperand(op1).asInt32();
1664 
1665             move(Imm32(op1imm), regT0);
1666             convertInt32ToDouble(regT0, fpRegT0);
1667 
1668             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1669 
1670             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1671 
1672 #if USE(JSVALUE64)
1673             fail1.link(this);
1674 #else
1675             if (!m_codeBlock->isKnownNotImmediate(op2))
1676                 fail1.link(this);
1677             fail2.link(this);
1678 #endif
1679         }
1680 
1681         JITStubCall stubCall(this, cti_op_jless);
1682         stubCall.addArgument(op1, regT2);
1683         stubCall.addArgument(regT1);
1684         stubCall.call();
1685         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
1686 
1687     } else {
1688         linkSlowCase(iter);
1689 
1690         if (supportsFloatingPoint()) {
1691 #if USE(JSVALUE64)
1692             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1693             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1694             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1695             addPtr(tagTypeNumberRegister, regT0);
1696             addPtr(tagTypeNumberRegister, regT1);
1697             movePtrToDouble(regT0, fpRegT0);
1698             movePtrToDouble(regT1, fpRegT1);
1699 #else
1700             Jump fail1;
1701             if (!m_codeBlock->isKnownNotImmediate(op1))
1702                 fail1 = emitJumpIfNotJSCell(regT0);
1703 
1704             Jump fail2;
1705             if (!m_codeBlock->isKnownNotImmediate(op2))
1706                 fail2 = emitJumpIfNotJSCell(regT1);
1707 
1708             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1709             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1710             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1711             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1712 #endif
1713 
1714             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1715 
1716             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1717 
1718 #if USE(JSVALUE64)
1719             fail1.link(this);
1720             fail2.link(this);
1721             fail3.link(this);
1722 #else
1723             if (!m_codeBlock->isKnownNotImmediate(op1))
1724                 fail1.link(this);
1725             if (!m_codeBlock->isKnownNotImmediate(op2))
1726                 fail2.link(this);
1727             fail3.link(this);
1728             fail4.link(this);
1729 #endif
1730         }
1731 
1732         linkSlowCase(iter);
1733         JITStubCall stubCall(this, cti_op_jless);
1734         stubCall.addArgument(regT0);
1735         stubCall.addArgument(regT1);
1736         stubCall.call();
1737         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
1738     }
1739 }
1740 
1741 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
1742 {
1743     unsigned op1 = currentInstruction[1].u.operand;
1744     unsigned op2 = currentInstruction[2].u.operand;
1745     unsigned target = currentInstruction[3].u.operand;
1746 
1747     // We generate inline code for the following cases in the fast path:
1748     // - int immediate to constant int immediate
1749     // - constant int immediate to int immediate
1750     // - int immediate to int immediate
1751 
1752     if (isOperandConstantImmediateInt(op2)) {
1753         emitGetVirtualRegister(op1, regT0);
1754         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1755 #if USE(JSVALUE64)
1756         int32_t op2imm = getConstantOperandImmediateInt(op2);
1757 #else
1758         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1759 #endif
1760         addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target);
1761     } else if (isOperandConstantImmediateInt(op1)) {
1762         emitGetVirtualRegister(op2, regT1);
1763         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1764 #if USE(JSVALUE64)
1765         int32_t op1imm = getConstantOperandImmediateInt(op1);
1766 #else
1767         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1768 #endif
1769         addJump(branch32(LessThan, regT1, Imm32(op1imm)), target);
1770     } else {
1771         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1772         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1773         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1774 
1775         addJump(branch32(GreaterThan, regT0, regT1), target);
1776     }
1777 }
1778 
1779 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1780 {
1781     unsigned op1 = currentInstruction[1].u.operand;
1782     unsigned op2 = currentInstruction[2].u.operand;
1783     unsigned target = currentInstruction[3].u.operand;
1784 
1785     // We generate inline code for the following cases in the slow path:
1786     // - floating-point number to constant int immediate
1787     // - constant int immediate to floating-point number
1788     // - floating-point number to floating-point number.
1789 
1790     if (isOperandConstantImmediateInt(op2)) {
1791         linkSlowCase(iter);
1792 
1793         if (supportsFloatingPoint()) {
1794 #if USE(JSVALUE64)
1795             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1796             addPtr(tagTypeNumberRegister, regT0);
1797             movePtrToDouble(regT0, fpRegT0);
1798 #else
1799             Jump fail1;
1800             if (!m_codeBlock->isKnownNotImmediate(op1))
1801                 fail1 = emitJumpIfNotJSCell(regT0);
1802 
1803             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1804             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1805 #endif
1806 
1807             int32_t op2imm = getConstantOperand(op2).asInt32();;
1808 
1809             move(Imm32(op2imm), regT1);
1810             convertInt32ToDouble(regT1, fpRegT1);
1811 
1812             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1813 
1814             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1815 
1816 #if USE(JSVALUE64)
1817             fail1.link(this);
1818 #else
1819             if (!m_codeBlock->isKnownNotImmediate(op1))
1820                 fail1.link(this);
1821             fail2.link(this);
1822 #endif
1823         }
1824 
1825         JITStubCall stubCall(this, cti_op_jlesseq);
1826         stubCall.addArgument(regT0);
1827         stubCall.addArgument(op2, regT2);
1828         stubCall.call();
1829         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1830 
1831     } else if (isOperandConstantImmediateInt(op1)) {
1832         linkSlowCase(iter);
1833 
1834         if (supportsFloatingPoint()) {
1835 #if USE(JSVALUE64)
1836             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1837             addPtr(tagTypeNumberRegister, regT1);
1838             movePtrToDouble(regT1, fpRegT1);
1839 #else
1840             Jump fail1;
1841             if (!m_codeBlock->isKnownNotImmediate(op2))
1842                 fail1 = emitJumpIfNotJSCell(regT1);
1843 
1844             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1845             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1846 #endif
1847 
1848             int32_t op1imm = getConstantOperand(op1).asInt32();;
1849 
1850             move(Imm32(op1imm), regT0);
1851             convertInt32ToDouble(regT0, fpRegT0);
1852 
1853             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1854 
1855             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1856 
1857 #if USE(JSVALUE64)
1858             fail1.link(this);
1859 #else
1860             if (!m_codeBlock->isKnownNotImmediate(op2))
1861                 fail1.link(this);
1862             fail2.link(this);
1863 #endif
1864         }
1865 
1866         JITStubCall stubCall(this, cti_op_jlesseq);
1867         stubCall.addArgument(op1, regT2);
1868         stubCall.addArgument(regT1);
1869         stubCall.call();
1870         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1871 
1872     } else {
1873         linkSlowCase(iter);
1874 
1875         if (supportsFloatingPoint()) {
1876 #if USE(JSVALUE64)
1877             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1878             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1879             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1880             addPtr(tagTypeNumberRegister, regT0);
1881             addPtr(tagTypeNumberRegister, regT1);
1882             movePtrToDouble(regT0, fpRegT0);
1883             movePtrToDouble(regT1, fpRegT1);
1884 #else
1885             Jump fail1;
1886             if (!m_codeBlock->isKnownNotImmediate(op1))
1887                 fail1 = emitJumpIfNotJSCell(regT0);
1888 
1889             Jump fail2;
1890             if (!m_codeBlock->isKnownNotImmediate(op2))
1891                 fail2 = emitJumpIfNotJSCell(regT1);
1892 
1893             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1894             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1895             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1896             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1897 #endif
1898 
1899             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1900 
1901             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1902 
1903 #if USE(JSVALUE64)
1904             fail1.link(this);
1905             fail2.link(this);
1906             fail3.link(this);
1907 #else
1908             if (!m_codeBlock->isKnownNotImmediate(op1))
1909                 fail1.link(this);
1910             if (!m_codeBlock->isKnownNotImmediate(op2))
1911                 fail2.link(this);
1912             fail3.link(this);
1913             fail4.link(this);
1914 #endif
1915         }
1916 
1917         linkSlowCase(iter);
1918         JITStubCall stubCall(this, cti_op_jlesseq);
1919         stubCall.addArgument(regT0);
1920         stubCall.addArgument(regT1);
1921         stubCall.call();
1922         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1923     }
1924 }
1925 
1926 void JIT::emit_op_bitand(Instruction* currentInstruction)
1927 {
1928     unsigned result = currentInstruction[1].u.operand;
1929     unsigned op1 = currentInstruction[2].u.operand;
1930     unsigned op2 = currentInstruction[3].u.operand;
1931 
1932     if (isOperandConstantImmediateInt(op1)) {
1933         emitGetVirtualRegister(op2, regT0);
1934         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1935 #if USE(JSVALUE64)
1936         int32_t imm = getConstantOperandImmediateInt(op1);
1937         andPtr(Imm32(imm), regT0);
1938         if (imm >= 0)
1939             emitFastArithIntToImmNoCheck(regT0, regT0);
1940 #else
1941         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);
1942 #endif
1943     } else if (isOperandConstantImmediateInt(op2)) {
1944         emitGetVirtualRegister(op1, regT0);
1945         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1946 #if USE(JSVALUE64)
1947         int32_t imm = getConstantOperandImmediateInt(op2);
1948         andPtr(Imm32(imm), regT0);
1949         if (imm >= 0)
1950             emitFastArithIntToImmNoCheck(regT0, regT0);
1951 #else
1952         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);
1953 #endif
1954     } else {
1955         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1956         andPtr(regT1, regT0);
1957         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1958     }
1959     emitPutVirtualRegister(result);
1960 }
1961 
1962 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1963 {
1964     unsigned result = currentInstruction[1].u.operand;
1965     unsigned op1 = currentInstruction[2].u.operand;
1966     unsigned op2 = currentInstruction[3].u.operand;
1967 
1968     linkSlowCase(iter);
1969     if (isOperandConstantImmediateInt(op1)) {
1970         JITStubCall stubCall(this, cti_op_bitand);
1971         stubCall.addArgument(op1, regT2);
1972         stubCall.addArgument(regT0);
1973         stubCall.call(result);
1974     } else if (isOperandConstantImmediateInt(op2)) {
1975         JITStubCall stubCall(this, cti_op_bitand);
1976         stubCall.addArgument(regT0);
1977         stubCall.addArgument(op2, regT2);
1978         stubCall.call(result);
1979     } else {
1980         JITStubCall stubCall(this, cti_op_bitand);
1981         stubCall.addArgument(op1, regT2);
1982         stubCall.addArgument(regT1);
1983         stubCall.call(result);
1984     }
1985 }
1986 
1987 void JIT::emit_op_post_inc(Instruction* currentInstruction)
1988 {
1989     unsigned result = currentInstruction[1].u.operand;
1990     unsigned srcDst = currentInstruction[2].u.operand;
1991 
1992     emitGetVirtualRegister(srcDst, regT0);
1993     move(regT0, regT1);
1994     emitJumpSlowCaseIfNotImmediateInteger(regT0);
1995 #if USE(JSVALUE64)
1996     addSlowCase(branchAdd32(Overflow, Imm32(1), regT1));
1997     emitFastArithIntToImmNoCheck(regT1, regT1);
1998 #else
1999     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
2000     signExtend32ToPtr(regT1, regT1);
2001 #endif
2002     emitPutVirtualRegister(srcDst, regT1);
2003     emitPutVirtualRegister(result);
2004 }
2005 
2006 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2007 {
2008     unsigned result = currentInstruction[1].u.operand;
2009     unsigned srcDst = currentInstruction[2].u.operand;
2010 
2011     linkSlowCase(iter);
2012     linkSlowCase(iter);
2013     JITStubCall stubCall(this, cti_op_post_inc);
2014     stubCall.addArgument(regT0);
2015     stubCall.addArgument(Imm32(srcDst));
2016     stubCall.call(result);
2017 }
2018 
2019 void JIT::emit_op_post_dec(Instruction* currentInstruction)
2020 {
2021     unsigned result = currentInstruction[1].u.operand;
2022     unsigned srcDst = currentInstruction[2].u.operand;
2023 
2024     emitGetVirtualRegister(srcDst, regT0);
2025     move(regT0, regT1);
2026     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2027 #if USE(JSVALUE64)
2028     addSlowCase(branchSub32(Zero, Imm32(1), regT1));
2029     emitFastArithIntToImmNoCheck(regT1, regT1);
2030 #else
2031     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
2032     signExtend32ToPtr(regT1, regT1);
2033 #endif
2034     emitPutVirtualRegister(srcDst, regT1);
2035     emitPutVirtualRegister(result);
2036 }
2037 
2038 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2039 {
2040     unsigned result = currentInstruction[1].u.operand;
2041     unsigned srcDst = currentInstruction[2].u.operand;
2042 
2043     linkSlowCase(iter);
2044     linkSlowCase(iter);
2045     JITStubCall stubCall(this, cti_op_post_dec);
2046     stubCall.addArgument(regT0);
2047     stubCall.addArgument(Imm32(srcDst));
2048     stubCall.call(result);
2049 }
2050 
2051 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
2052 {
2053     unsigned srcDst = currentInstruction[1].u.operand;
2054 
2055     emitGetVirtualRegister(srcDst, regT0);
2056     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2057 #if USE(JSVALUE64)
2058     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
2059     emitFastArithIntToImmNoCheck(regT0, regT0);
2060 #else
2061     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
2062     signExtend32ToPtr(regT0, regT0);
2063 #endif
2064     emitPutVirtualRegister(srcDst);
2065 }
2066 
2067 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2068 {
2069     unsigned srcDst = currentInstruction[1].u.operand;
2070 
2071     Jump notImm = getSlowCase(iter);
2072     linkSlowCase(iter);
2073     emitGetVirtualRegister(srcDst, regT0);
2074     notImm.link(this);
2075     JITStubCall stubCall(this, cti_op_pre_inc);
2076     stubCall.addArgument(regT0);
2077     stubCall.call(srcDst);
2078 }
2079 
2080 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
2081 {
2082     unsigned srcDst = currentInstruction[1].u.operand;
2083 
2084     emitGetVirtualRegister(srcDst, regT0);
2085     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2086 #if USE(JSVALUE64)
2087     addSlowCase(branchSub32(Zero, Imm32(1), regT0));
2088     emitFastArithIntToImmNoCheck(regT0, regT0);
2089 #else
2090     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
2091     signExtend32ToPtr(regT0, regT0);
2092 #endif
2093     emitPutVirtualRegister(srcDst);
2094 }
2095 
2096 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2097 {
2098     unsigned srcDst = currentInstruction[1].u.operand;
2099 
2100     Jump notImm = getSlowCase(iter);
2101     linkSlowCase(iter);
2102     emitGetVirtualRegister(srcDst, regT0);
2103     notImm.link(this);
2104     JITStubCall stubCall(this, cti_op_pre_dec);
2105     stubCall.addArgument(regT0);
2106     stubCall.call(srcDst);
2107 }
2108 
2109 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
2110 
2111 #if CPU(X86) || CPU(X86_64)
2112 
2113 void JIT::emit_op_mod(Instruction* currentInstruction)
2114 {
2115     unsigned result = currentInstruction[1].u.operand;
2116     unsigned op1 = currentInstruction[2].u.operand;
2117     unsigned op2 = currentInstruction[3].u.operand;
2118 
2119     emitGetVirtualRegisters(op1, X86Registers::eax, op2, X86Registers::ecx);
2120     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax);
2121     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx);
2122 #if USE(JSVALUE64)
2123     addSlowCase(branchPtr(Equal, X86Registers::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
2124     m_assembler.cdq();
2125     m_assembler.idivl_r(X86Registers::ecx);
2126 #else
2127     emitFastArithDeTagImmediate(X86Registers::eax);
2128     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx));
2129     m_assembler.cdq();
2130     m_assembler.idivl_r(X86Registers::ecx);
2131     signExtend32ToPtr(X86Registers::edx, X86Registers::edx);
2132 #endif
2133     emitFastArithReTagImmediate(X86Registers::edx, X86Registers::eax);
2134     emitPutVirtualRegister(result);
2135 }
2136 
2137 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2138 {
2139     unsigned result = currentInstruction[1].u.operand;
2140 
2141 #if USE(JSVALUE64)
2142     linkSlowCase(iter);
2143     linkSlowCase(iter);
2144     linkSlowCase(iter);
2145 #else
2146     Jump notImm1 = getSlowCase(iter);
2147     Jump notImm2 = getSlowCase(iter);
2148     linkSlowCase(iter);
2149     emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax);
2150     emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx);
2151     notImm1.link(this);
2152     notImm2.link(this);
2153 #endif
2154     JITStubCall stubCall(this, cti_op_mod);
2155     stubCall.addArgument(X86Registers::eax);
2156     stubCall.addArgument(X86Registers::ecx);
2157     stubCall.call(result);
2158 }
2159 
2160 #else // CPU(X86) || CPU(X86_64)
2161 
2162 void JIT::emit_op_mod(Instruction* currentInstruction)
2163 {
2164     unsigned result = currentInstruction[1].u.operand;
2165     unsigned op1 = currentInstruction[2].u.operand;
2166     unsigned op2 = currentInstruction[3].u.operand;
2167 
2168 #if ENABLE(JIT_OPTIMIZE_MOD)
2169     emitGetVirtualRegisters(op1, regT0, op2, regT2);
2170     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2171     emitJumpSlowCaseIfNotImmediateInteger(regT2);
2172 
2173     addSlowCase(branch32(Equal, regT2, Imm32(1)));
2174 
2175     emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
2176 
2177     emitPutVirtualRegister(result, regT0);
2178 #else
2179     JITStubCall stubCall(this, cti_op_mod);
2180     stubCall.addArgument(op1, regT2);
2181     stubCall.addArgument(op2, regT2);
2182     stubCall.call(result);
2183 #endif
2184 }
2185 
2186 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2187 {
2188 #if ENABLE(JIT_OPTIMIZE_MOD)
2189     unsigned result = currentInstruction[1].u.operand;
2190     unsigned op1 = currentInstruction[2].u.operand;
2191     unsigned op2 = currentInstruction[3].u.operand;
2192     linkSlowCase(iter);
2193     linkSlowCase(iter);
2194     linkSlowCase(iter);
2195     JITStubCall stubCall(this, cti_op_mod);
2196     stubCall.addArgument(op1, regT2);
2197     stubCall.addArgument(op2, regT2);
2198     stubCall.call(result);
2199 #else
2200     ASSERT_NOT_REACHED();
2201 #endif
2202 }
2203 
2204 #endif // CPU(X86) || CPU(X86_64)
2205 
2206 /* ------------------------------ END: OP_MOD ------------------------------ */
2207 
2208 #if USE(JSVALUE64)
2209 
2210 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2211 
2212 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
2213 {
2214     emitGetVirtualRegisters(op1, regT0, op2, regT1);
2215     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2216     emitJumpSlowCaseIfNotImmediateInteger(regT1);
2217     if (opcodeID == op_add)
2218         addSlowCase(branchAdd32(Overflow, regT1, regT0));
2219     else if (opcodeID == op_sub)
2220         addSlowCase(branchSub32(Overflow, regT1, regT0));
2221     else {
2222         ASSERT(opcodeID == op_mul);
2223         addSlowCase(branchMul32(Overflow, regT1, regT0));
2224         addSlowCase(branchTest32(Zero, regT0));
2225     }
2226     emitFastArithIntToImmNoCheck(regT0, regT0);
2227 }
2228 
2229 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
2230 {
2231     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
2232     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
2233 
2234     Jump notImm1;
2235     Jump notImm2;
2236     if (op1HasImmediateIntFastCase) {
2237         notImm2 = getSlowCase(iter);
2238     } else if (op2HasImmediateIntFastCase) {
2239         notImm1 = getSlowCase(iter);
2240     } else {
2241         notImm1 = getSlowCase(iter);
2242         notImm2 = getSlowCase(iter);
2243     }
2244 
2245     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
2246     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
2247         linkSlowCase(iter);
2248     emitGetVirtualRegister(op1, regT0);
2249 
2250     Label stubFunctionCall(this);
2251     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
2252     if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) {
2253         emitGetVirtualRegister(op1, regT0);
2254         emitGetVirtualRegister(op2, regT1);
2255     }
2256     stubCall.addArgument(regT0);
2257     stubCall.addArgument(regT1);
2258     stubCall.call(result);
2259     Jump end = jump();
2260 
2261     if (op1HasImmediateIntFastCase) {
2262         notImm2.link(this);
2263         if (!types.second().definitelyIsNumber())
2264             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2265         emitGetVirtualRegister(op1, regT1);
2266         convertInt32ToDouble(regT1, fpRegT1);
2267         addPtr(tagTypeNumberRegister, regT0);
2268         movePtrToDouble(regT0, fpRegT2);
2269     } else if (op2HasImmediateIntFastCase) {
2270         notImm1.link(this);
2271         if (!types.first().definitelyIsNumber())
2272             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2273         emitGetVirtualRegister(op2, regT1);
2274         convertInt32ToDouble(regT1, fpRegT1);
2275         addPtr(tagTypeNumberRegister, regT0);
2276         movePtrToDouble(regT0, fpRegT2);
2277     } else {
2278         // if we get here, eax is not an int32, edx not yet checked.
2279         notImm1.link(this);
2280         if (!types.first().definitelyIsNumber())
2281             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2282         if (!types.second().definitelyIsNumber())
2283             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
2284         addPtr(tagTypeNumberRegister, regT0);
2285         movePtrToDouble(regT0, fpRegT1);
2286         Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
2287         convertInt32ToDouble(regT1, fpRegT2);
2288         Jump op2wasInteger = jump();
2289 
2290         // if we get here, eax IS an int32, edx is not.
2291         notImm2.link(this);
2292         if (!types.second().definitelyIsNumber())
2293             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
2294         convertInt32ToDouble(regT0, fpRegT1);
2295         op2isDouble.link(this);
2296         addPtr(tagTypeNumberRegister, regT1);
2297         movePtrToDouble(regT1, fpRegT2);
2298         op2wasInteger.link(this);
2299     }
2300 
2301     if (opcodeID == op_add)
2302         addDouble(fpRegT2, fpRegT1);
2303     else if (opcodeID == op_sub)
2304         subDouble(fpRegT2, fpRegT1);
2305     else if (opcodeID == op_mul)
2306         mulDouble(fpRegT2, fpRegT1);
2307     else {
2308         ASSERT(opcodeID == op_div);
2309         divDouble(fpRegT2, fpRegT1);
2310     }
2311     moveDoubleToPtr(fpRegT1, regT0);
2312     subPtr(tagTypeNumberRegister, regT0);
2313     emitPutVirtualRegister(result, regT0);
2314 
2315     end.link(this);
2316 }
2317 
2318 void JIT::emit_op_add(Instruction* currentInstruction)
2319 {
2320     unsigned result = currentInstruction[1].u.operand;
2321     unsigned op1 = currentInstruction[2].u.operand;
2322     unsigned op2 = currentInstruction[3].u.operand;
2323     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2324 
2325     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
2326         JITStubCall stubCall(this, cti_op_add);
2327         stubCall.addArgument(op1, regT2);
2328         stubCall.addArgument(op2, regT2);
2329         stubCall.call(result);
2330         return;
2331     }
2332 
2333     if (isOperandConstantImmediateInt(op1)) {
2334         emitGetVirtualRegister(op2, regT0);
2335         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2336         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
2337         emitFastArithIntToImmNoCheck(regT0, regT0);
2338     } else if (isOperandConstantImmediateInt(op2)) {
2339         emitGetVirtualRegister(op1, regT0);
2340         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2341         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
2342         emitFastArithIntToImmNoCheck(regT0, regT0);
2343     } else
2344         compileBinaryArithOp(op_add, result, op1, op2, types);
2345 
2346     emitPutVirtualRegister(result);
2347 }
2348 
2349 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2350 {
2351     unsigned result = currentInstruction[1].u.operand;
2352     unsigned op1 = currentInstruction[2].u.operand;
2353     unsigned op2 = currentInstruction[3].u.operand;
2354     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2355 
2356     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
2357         return;
2358 
2359     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
2360     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
2361     compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
2362 }
2363 
2364 void JIT::emit_op_mul(Instruction* currentInstruction)
2365 {
2366     unsigned result = currentInstruction[1].u.operand;
2367     unsigned op1 = currentInstruction[2].u.operand;
2368     unsigned op2 = currentInstruction[3].u.operand;
2369     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2370 
2371     // For now, only plant a fast int case if the constant operand is greater than zero.
2372     int32_t value;
2373     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
2374         emitGetVirtualRegister(op2, regT0);
2375         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2376         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2377         emitFastArithReTagImmediate(regT0, regT0);
2378     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
2379         emitGetVirtualRegister(op1, regT0);
2380         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2381         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2382         emitFastArithReTagImmediate(regT0, regT0);
2383     } else
2384         compileBinaryArithOp(op_mul, result, op1, op2, types);
2385 
2386     emitPutVirtualRegister(result);
2387 }
2388 
2389 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2390 {
2391     unsigned result = currentInstruction[1].u.operand;
2392     unsigned op1 = currentInstruction[2].u.operand;
2393     unsigned op2 = currentInstruction[3].u.operand;
2394     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2395 
2396     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
2397     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
2398     compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
2399 }
2400 
2401 void JIT::emit_op_div(Instruction* currentInstruction)
2402 {
2403     unsigned dst = currentInstruction[1].u.operand;
2404     unsigned op1 = currentInstruction[2].u.operand;
2405     unsigned op2 = currentInstruction[3].u.operand;
2406     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2407 
2408     if (isOperandConstantImmediateDouble(op1)) {
2409         emitGetVirtualRegister(op1, regT0);
2410         addPtr(tagTypeNumberRegister, regT0);
2411         movePtrToDouble(regT0, fpRegT0);
2412     } else if (isOperandConstantImmediateInt(op1)) {
2413         emitLoadInt32ToDouble(op1, fpRegT0);
2414     } else {
2415         emitGetVirtualRegister(op1, regT0);
2416         if (!types.first().definitelyIsNumber())
2417             emitJumpSlowCaseIfNotImmediateNumber(regT0);
2418         Jump notInt = emitJumpIfNotImmediateInteger(regT0);
2419         convertInt32ToDouble(regT0, fpRegT0);
2420         Jump skipDoubleLoad = jump();
2421         notInt.link(this);
2422         addPtr(tagTypeNumberRegister, regT0);
2423         movePtrToDouble(regT0, fpRegT0);
2424         skipDoubleLoad.link(this);
2425     }
2426 
2427     if (isOperandConstantImmediateDouble(op2)) {
2428         emitGetVirtualRegister(op2, regT1);
2429         addPtr(tagTypeNumberRegister, regT1);
2430         movePtrToDouble(regT1, fpRegT1);
2431     } else if (isOperandConstantImmediateInt(op2)) {
2432         emitLoadInt32ToDouble(op2, fpRegT1);
2433     } else {
2434         emitGetVirtualRegister(op2, regT1);
2435         if (!types.second().definitelyIsNumber())
2436             emitJumpSlowCaseIfNotImmediateNumber(regT1);
2437         Jump notInt = emitJumpIfNotImmediateInteger(regT1);
2438         convertInt32ToDouble(regT1, fpRegT1);
2439         Jump skipDoubleLoad = jump();
2440         notInt.link(this);
2441         addPtr(tagTypeNumberRegister, regT1);
2442         movePtrToDouble(regT1, fpRegT1);
2443         skipDoubleLoad.link(this);
2444     }
2445     divDouble(fpRegT1, fpRegT0);
2446 
2447     // Double result.
2448     moveDoubleToPtr(fpRegT0, regT0);
2449     subPtr(tagTypeNumberRegister, regT0);
2450 
2451     emitPutVirtualRegister(dst, regT0);
2452 }
2453 
2454 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2455 {
2456     unsigned result = currentInstruction[1].u.operand;
2457     unsigned op1 = currentInstruction[2].u.operand;
2458     unsigned op2 = currentInstruction[3].u.operand;
2459     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2460     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
2461 #ifndef NDEBUG
2462         breakpoint();
2463 #endif
2464         return;
2465     }
2466     if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
2467         if (!types.first().definitelyIsNumber())
2468             linkSlowCase(iter);
2469     }
2470     if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
2471         if (!types.second().definitelyIsNumber())
2472             linkSlowCase(iter);
2473     }
2474     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2475     JITStubCall stubCall(this, cti_op_div);
2476     stubCall.addArgument(op1, regT2);
2477     stubCall.addArgument(op2, regT2);
2478     stubCall.call(result);
2479 }
2480 
2481 void JIT::emit_op_sub(Instruction* currentInstruction)
2482 {
2483     unsigned result = currentInstruction[1].u.operand;
2484     unsigned op1 = currentInstruction[2].u.operand;
2485     unsigned op2 = currentInstruction[3].u.operand;
2486     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2487 
2488     compileBinaryArithOp(op_sub, result, op1, op2, types);
2489     emitPutVirtualRegister(result);
2490 }
2491 
2492 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2493 {
2494     unsigned result = currentInstruction[1].u.operand;
2495     unsigned op1 = currentInstruction[2].u.operand;
2496     unsigned op2 = currentInstruction[3].u.operand;
2497     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2498 
2499     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
2500 }
2501 
2502 #else // USE(JSVALUE64)
2503 
2504 /* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2505 
2506 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
2507 {
2508     Structure* numberStructure = m_globalData->numberStructure.get();
2509     Jump wasJSNumberCell1;
2510     Jump wasJSNumberCell2;
2511 
2512     emitGetVirtualRegisters(src1, regT0, src2, regT1);
2513 
2514     if (types.second().isReusable() && supportsFloatingPoint()) {
2515         ASSERT(types.second().mightBeNumber());
2516 
2517         // Check op2 is a number
2518         Jump op2imm = emitJumpIfImmediateInteger(regT1);
2519         if (!types.second().definitelyIsNumber()) {
2520             emitJumpSlowCaseIfNotJSCell(regT1, src2);
2521             addSlowCase(checkStructure(regT1, numberStructure));
2522         }
2523 
2524         // (1) In this case src2 is a reusable number cell.
2525         //     Slow case if src1 is not a number type.
2526         Jump op1imm = emitJumpIfImmediateInteger(regT0);
2527         if (!types.first().definitelyIsNumber()) {
2528             emitJumpSlowCaseIfNotJSCell(regT0, src1);
2529             addSlowCase(checkStructure(regT0, numberStructure));
2530         }
2531 
2532         // (1a) if we get here, src1 is also a number cell
2533         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2534         Jump loadedDouble = jump();
2535         // (1b) if we get here, src1 is an immediate
2536         op1imm.link(this);
2537         emitFastArithImmToInt(regT0);
2538         convertInt32ToDouble(regT0, fpRegT0);
2539         // (1c)
2540         loadedDouble.link(this);
2541         if (opcodeID == op_add)
2542             addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2543         else if (opcodeID == op_sub)
2544             subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2545         else {
2546             ASSERT(opcodeID == op_mul);
2547             mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2548         }
2549 
2550         // Store the result to the JSNumberCell and jump.
2551         storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2552         move(regT1, regT0);
2553         emitPutVirtualRegister(dst);
2554         wasJSNumberCell2 = jump();
2555 
2556         // (2) This handles cases where src2 is an immediate number.
2557         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
2558         op2imm.link(this);
2559         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2560     } else if (types.first().isReusable() && supportsFloatingPoint()) {
2561         ASSERT(types.first().mightBeNumber());
2562 
2563         // Check op1 is a number
2564         Jump op1imm = emitJumpIfImmediateInteger(regT0);
2565         if (!types.first().definitelyIsNumber()) {
2566             emitJumpSlowCaseIfNotJSCell(regT0, src1);
2567             addSlowCase(checkStructure(regT0, numberStructure));
2568         }
2569 
2570         // (1) In this case src1 is a reusable number cell.
2571         //     Slow case if src2 is not a number type.
2572         Jump op2imm = emitJumpIfImmediateInteger(regT1);
2573         if (!types.second().definitelyIsNumber()) {
2574             emitJumpSlowCaseIfNotJSCell(regT1, src2);
2575             addSlowCase(checkStructure(regT1, numberStructure));
2576         }
2577 
2578         // (1a) if we get here, src2 is also a number cell
2579         loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
2580         Jump loadedDouble = jump();
2581         // (1b) if we get here, src2 is an immediate
2582         op2imm.link(this);
2583         emitFastArithImmToInt(regT1);
2584         convertInt32ToDouble(regT1, fpRegT1);
2585         // (1c)
2586         loadedDouble.link(this);
2587         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2588         if (opcodeID == op_add)
2589             addDouble(fpRegT1, fpRegT0);
2590         else if (opcodeID == op_sub)
2591             subDouble(fpRegT1, fpRegT0);
2592         else {
2593             ASSERT(opcodeID == op_mul);
2594             mulDouble(fpRegT1, fpRegT0);
2595         }
2596         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2597         emitPutVirtualRegister(dst);
2598 
2599         // Store the result to the JSNumberCell and jump.
2600         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2601         emitPutVirtualRegister(dst);
2602         wasJSNumberCell1 = jump();
2603 
2604         // (2) This handles cases where src1 is an immediate number.
2605         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
2606         op1imm.link(this);
2607         emitJumpSlowCaseIfNotImmediateInteger(regT1);
2608     } else
2609         emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2610 
2611     if (opcodeID == op_add) {
2612         emitFastArithDeTagImmediate(regT0);
2613         addSlowCase(branchAdd32(Overflow, regT1, regT0));
2614     } else  if (opcodeID == op_sub) {
2615         addSlowCase(branchSub32(Overflow, regT1, regT0));
2616         signExtend32ToPtr(regT0, regT0);
2617         emitFastArithReTagImmediate(regT0, regT0);
2618     } else {
2619         ASSERT(opcodeID == op_mul);
2620         // convert eax & edx from JSImmediates to ints, and check if either are zero
2621         emitFastArithImmToInt(regT1);
2622         Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0);
2623         Jump op2NonZero = branchTest32(NonZero, regT1);
2624         op1Zero.link(this);
2625         // if either input is zero, add the two together, and check if the result is < 0.
2626         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
2627         move(regT0, regT2);
2628         addSlowCase(branchAdd32(Signed, regT1, regT2));
2629         // Skip the above check if neither input is zero
2630         op2NonZero.link(this);
2631         addSlowCase(branchMul32(Overflow, regT1, regT0));
2632         signExtend32ToPtr(regT0, regT0);
2633         emitFastArithReTagImmediate(regT0, regT0);
2634     }
2635     emitPutVirtualRegister(dst);
2636 
2637     if (types.second().isReusable() && supportsFloatingPoint())
2638         wasJSNumberCell2.link(this);
2639     else if (types.first().isReusable() && supportsFloatingPoint())
2640         wasJSNumberCell1.link(this);
2641 }
2642 
2643 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
2644 {
2645     linkSlowCase(iter);
2646     if (types.second().isReusable() && supportsFloatingPoint()) {
2647         if (!types.first().definitelyIsNumber()) {
2648             linkSlowCaseIfNotJSCell(iter, src1);
2649             linkSlowCase(iter);
2650         }
2651         if (!types.second().definitelyIsNumber()) {
2652             linkSlowCaseIfNotJSCell(iter, src2);
2653             linkSlowCase(iter);
2654         }
2655     } else if (types.first().isReusable() && supportsFloatingPoint()) {
2656         if (!types.first().definitelyIsNumber()) {
2657             linkSlowCaseIfNotJSCell(iter, src1);
2658             linkSlowCase(iter);
2659         }
2660         if (!types.second().definitelyIsNumber()) {
2661             linkSlowCaseIfNotJSCell(iter, src2);
2662             linkSlowCase(iter);
2663         }
2664     }
2665     linkSlowCase(iter);
2666 
2667     // additional entry point to handle -0 cases.
2668     if (opcodeID == op_mul)
2669         linkSlowCase(iter);
2670 
2671     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
2672     stubCall.addArgument(src1, regT2);
2673     stubCall.addArgument(src2, regT2);
2674     stubCall.call(dst);
2675 }
2676 
2677 void JIT::emit_op_add(Instruction* currentInstruction)
2678 {
2679     unsigned result = currentInstruction[1].u.operand;
2680     unsigned op1 = currentInstruction[2].u.operand;
2681     unsigned op2 = currentInstruction[3].u.operand;
2682     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2683 
2684     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
2685         JITStubCall stubCall(this, cti_op_add);
2686         stubCall.addArgument(op1, regT2);
2687         stubCall.addArgument(op2, regT2);
2688         stubCall.call(result);
2689         return;
2690     }
2691 
2692     if (isOperandConstantImmediateInt(op1)) {
2693         emitGetVirtualRegister(op2, regT0);
2694         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2695         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0));
2696         signExtend32ToPtr(regT0, regT0);
2697         emitPutVirtualRegister(result);
2698     } else if (isOperandConstantImmediateInt(op2)) {
2699         emitGetVirtualRegister(op1, regT0);
2700         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2701         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0));
2702         signExtend32ToPtr(regT0, regT0);
2703         emitPutVirtualRegister(result);
2704     } else {
2705         compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2706     }
2707 }
2708 
2709 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2710 {
2711     unsigned result = currentInstruction[1].u.operand;
2712     unsigned op1 = currentInstruction[2].u.operand;
2713     unsigned op2 = currentInstruction[3].u.operand;
2714 
2715     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2716     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
2717         return;
2718 
2719     if (isOperandConstantImmediateInt(op1)) {
2720         Jump notImm = getSlowCase(iter);
2721         linkSlowCase(iter);
2722         sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0);
2723         notImm.link(this);
2724         JITStubCall stubCall(this, cti_op_add);
2725         stubCall.addArgument(op1, regT2);
2726         stubCall.addArgument(regT0);
2727         stubCall.call(result);
2728     } else if (isOperandConstantImmediateInt(op2)) {
2729         Jump notImm = getSlowCase(iter);
2730         linkSlowCase(iter);
2731         sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0);
2732         notImm.link(this);
2733         JITStubCall stubCall(this, cti_op_add);
2734         stubCall.addArgument(regT0);
2735         stubCall.addArgument(op2, regT2);
2736         stubCall.call(result);
2737     } else {
2738         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2739         ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
2740         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
2741     }
2742 }
2743 
2744 void JIT::emit_op_mul(Instruction* currentInstruction)
2745 {
2746     unsigned result = currentInstruction[1].u.operand;
2747     unsigned op1 = currentInstruction[2].u.operand;
2748     unsigned op2 = currentInstruction[3].u.operand;
2749 
2750     // For now, only plant a fast int case if the constant operand is greater than zero.
2751     int32_t value;
2752     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
2753         emitGetVirtualRegister(op2, regT0);
2754         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2755         emitFastArithDeTagImmediate(regT0);
2756         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2757         signExtend32ToPtr(regT0, regT0);
2758         emitFastArithReTagImmediate(regT0, regT0);
2759         emitPutVirtualRegister(result);
2760     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
2761         emitGetVirtualRegister(op1, regT0);
2762         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2763         emitFastArithDeTagImmediate(regT0);
2764         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2765         signExtend32ToPtr(regT0, regT0);
2766         emitFastArithReTagImmediate(regT0, regT0);
2767         emitPutVirtualRegister(result);
2768     } else
2769         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2770 }
2771 
2772 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2773 {
2774     unsigned result = currentInstruction[1].u.operand;
2775     unsigned op1 = currentInstruction[2].u.operand;
2776     unsigned op2 = currentInstruction[3].u.operand;
2777 
2778     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
2779         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
2780         linkSlowCase(iter);
2781         linkSlowCase(iter);
2782         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2783         JITStubCall stubCall(this, cti_op_mul);
2784         stubCall.addArgument(op1, regT2);
2785         stubCall.addArgument(op2, regT2);
2786         stubCall.call(result);
2787     } else
2788         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2789 }
2790 
2791 void JIT::emit_op_sub(Instruction* currentInstruction)
2792 {
2793     compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
2794 }
2795 
2796 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2797 {
2798     compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
2799 }
2800 
2801 #endif // USE(JSVALUE64)
2802 
2803 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
2804 
2805 #endif // USE(JSVALUE32_64)
2806 
2807 } // namespace JSC
2808 
2809 #endif // ENABLE(JIT)
2810