Hoist JSVALUE32_64 arithmetic implementations into a separate file.
[WebKit-https.git] / JavaScriptCore / jit / JITArithmetic.cpp
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
51 void JIT::emit_op_lshift(Instruction* currentInstruction)
52 {
53     unsigned result = currentInstruction[1].u.operand;
54     unsigned op1 = currentInstruction[2].u.operand;
55     unsigned op2 = currentInstruction[3].u.operand;
56
57     emitGetVirtualRegisters(op1, regT0, op2, regT2);
58     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
59     emitJumpSlowCaseIfNotImmediateInteger(regT0);
60     emitJumpSlowCaseIfNotImmediateInteger(regT2);
61     emitFastArithImmToInt(regT0);
62     emitFastArithImmToInt(regT2);
63     lshift32(regT2, regT0);
64 #if USE(JSVALUE32)
65     addSlowCase(branchAdd32(Overflow, regT0, regT0));
66     signExtend32ToPtr(regT0, regT0);
67 #endif
68     emitFastArithReTagImmediate(regT0, regT0);
69     emitPutVirtualRegister(result);
70 }
71
72 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
73 {
74     unsigned result = currentInstruction[1].u.operand;
75     unsigned op1 = currentInstruction[2].u.operand;
76     unsigned op2 = currentInstruction[3].u.operand;
77
78 #if USE(JSVALUE64)
79     UNUSED_PARAM(op1);
80     UNUSED_PARAM(op2);
81     linkSlowCase(iter);
82     linkSlowCase(iter);
83 #else
84     // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
85     Jump notImm1 = getSlowCase(iter);
86     Jump notImm2 = getSlowCase(iter);
87     linkSlowCase(iter);
88     emitGetVirtualRegisters(op1, regT0, op2, regT2);
89     notImm1.link(this);
90     notImm2.link(this);
91 #endif
92     JITStubCall stubCall(this, cti_op_lshift);
93     stubCall.addArgument(regT0);
94     stubCall.addArgument(regT2);
95     stubCall.call(result);
96 }
97
98 void JIT::emit_op_rshift(Instruction* currentInstruction)
99 {
100     unsigned result = currentInstruction[1].u.operand;
101     unsigned op1 = currentInstruction[2].u.operand;
102     unsigned op2 = currentInstruction[3].u.operand;
103
104     if (isOperandConstantImmediateInt(op2)) {
105         // isOperandConstantImmediateInt(op2) => 1 SlowCase
106         emitGetVirtualRegister(op1, regT0);
107         emitJumpSlowCaseIfNotImmediateInteger(regT0);
108         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
109         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
110     } else {
111         emitGetVirtualRegisters(op1, regT0, op2, regT2);
112         if (supportsFloatingPointTruncate()) {
113             Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
114 #if USE(JSVALUE64)
115             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
116             addSlowCase(emitJumpIfNotImmediateNumber(regT0));
117             addPtr(tagTypeNumberRegister, regT0);
118             movePtrToDouble(regT0, fpRegT0);
119             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
120 #else
121             // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell)
122             emitJumpSlowCaseIfNotJSCell(regT0, op1);
123             addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get()));
124             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
125             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
126             addSlowCase(branchAdd32(Overflow, regT0, regT0));
127 #endif
128             lhsIsInt.link(this);
129             emitJumpSlowCaseIfNotImmediateInteger(regT2);
130         } else {
131             // !supportsFloatingPoint() => 2 SlowCases
132             emitJumpSlowCaseIfNotImmediateInteger(regT0);
133             emitJumpSlowCaseIfNotImmediateInteger(regT2);
134         }
135         emitFastArithImmToInt(regT2);
136         rshift32(regT2, regT0);
137 #if USE(JSVALUE32)
138         signExtend32ToPtr(regT0, regT0);
139 #endif
140     }
141 #if USE(JSVALUE64)
142     emitFastArithIntToImmNoCheck(regT0, regT0);
143 #else
144     orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
145 #endif
146     emitPutVirtualRegister(result);
147 }
148
149 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
150 {
151     unsigned result = currentInstruction[1].u.operand;
152     unsigned op1 = currentInstruction[2].u.operand;
153     unsigned op2 = currentInstruction[3].u.operand;
154
155     JITStubCall stubCall(this, cti_op_rshift);
156
157     if (isOperandConstantImmediateInt(op2)) {
158         linkSlowCase(iter);
159         stubCall.addArgument(regT0);
160         stubCall.addArgument(op2, regT2);
161     } else {
162         if (supportsFloatingPointTruncate()) {
163 #if USE(JSVALUE64)
164             linkSlowCase(iter);
165             linkSlowCase(iter);
166             linkSlowCase(iter);
167 #else
168             linkSlowCaseIfNotJSCell(iter, op1);
169             linkSlowCase(iter);
170             linkSlowCase(iter);
171             linkSlowCase(iter);
172             linkSlowCase(iter);
173 #endif
174             // We're reloading op1 to regT0 as we can no longer guarantee that
175             // we have not munged the operand.  It may have already been shifted
176             // correctly, but it still will not have been tagged.
177             stubCall.addArgument(op1, regT0);
178             stubCall.addArgument(regT2);
179         } else {
180             linkSlowCase(iter);
181             linkSlowCase(iter);
182             stubCall.addArgument(regT0);
183             stubCall.addArgument(regT2);
184         }
185     }
186
187     stubCall.call(result);
188 }
189
190 void JIT::emit_op_jnless(Instruction* currentInstruction)
191 {
192     unsigned op1 = currentInstruction[1].u.operand;
193     unsigned op2 = currentInstruction[2].u.operand;
194     unsigned target = currentInstruction[3].u.operand;
195
196     // We generate inline code for the following cases in the fast path:
197     // - int immediate to constant int immediate
198     // - constant int immediate to int immediate
199     // - int immediate to int immediate
200
201     if (isOperandConstantImmediateInt(op2)) {
202         emitGetVirtualRegister(op1, regT0);
203         emitJumpSlowCaseIfNotImmediateInteger(regT0);
204 #if USE(JSVALUE64)
205         int32_t op2imm = getConstantOperandImmediateInt(op2);
206 #else
207         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
208 #endif
209         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
210     } else if (isOperandConstantImmediateInt(op1)) {
211         emitGetVirtualRegister(op2, regT1);
212         emitJumpSlowCaseIfNotImmediateInteger(regT1);
213 #if USE(JSVALUE64)
214         int32_t op1imm = getConstantOperandImmediateInt(op1);
215 #else
216         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
217 #endif
218         addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
219     } else {
220         emitGetVirtualRegisters(op1, regT0, op2, regT1);
221         emitJumpSlowCaseIfNotImmediateInteger(regT0);
222         emitJumpSlowCaseIfNotImmediateInteger(regT1);
223
224         addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
225     }
226 }
227
228 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
229 {
230     unsigned op1 = currentInstruction[1].u.operand;
231     unsigned op2 = currentInstruction[2].u.operand;
232     unsigned target = currentInstruction[3].u.operand;
233
234     // We generate inline code for the following cases in the slow path:
235     // - floating-point number to constant int immediate
236     // - constant int immediate to floating-point number
237     // - floating-point number to floating-point number.
238
239     if (isOperandConstantImmediateInt(op2)) {
240         linkSlowCase(iter);
241
242         if (supportsFloatingPoint()) {
243 #if USE(JSVALUE64)
244             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
245             addPtr(tagTypeNumberRegister, regT0);
246             movePtrToDouble(regT0, fpRegT0);
247 #else
248             Jump fail1;
249             if (!m_codeBlock->isKnownNotImmediate(op1))
250                 fail1 = emitJumpIfNotJSCell(regT0);
251
252             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
253             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
254 #endif
255
256             int32_t op2imm = getConstantOperand(op2).asInt32();;
257
258             move(Imm32(op2imm), regT1);
259             convertInt32ToDouble(regT1, fpRegT1);
260
261             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
262
263             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
264
265 #if USE(JSVALUE64)
266             fail1.link(this);
267 #else
268             if (!m_codeBlock->isKnownNotImmediate(op1))
269                 fail1.link(this);
270             fail2.link(this);
271 #endif
272         }
273
274         JITStubCall stubCall(this, cti_op_jless);
275         stubCall.addArgument(regT0);
276         stubCall.addArgument(op2, regT2);
277         stubCall.call();
278         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
279
280     } else if (isOperandConstantImmediateInt(op1)) {
281         linkSlowCase(iter);
282
283         if (supportsFloatingPoint()) {
284 #if USE(JSVALUE64)
285             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
286             addPtr(tagTypeNumberRegister, regT1);
287             movePtrToDouble(regT1, fpRegT1);
288 #else
289             Jump fail1;
290             if (!m_codeBlock->isKnownNotImmediate(op2))
291                 fail1 = emitJumpIfNotJSCell(regT1);
292
293             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
294             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
295 #endif
296
297             int32_t op1imm = getConstantOperand(op1).asInt32();;
298
299             move(Imm32(op1imm), regT0);
300             convertInt32ToDouble(regT0, fpRegT0);
301
302             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
303
304             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
305
306 #if USE(JSVALUE64)
307             fail1.link(this);
308 #else
309             if (!m_codeBlock->isKnownNotImmediate(op2))
310                 fail1.link(this);
311             fail2.link(this);
312 #endif
313         }
314
315         JITStubCall stubCall(this, cti_op_jless);
316         stubCall.addArgument(op1, regT2);
317         stubCall.addArgument(regT1);
318         stubCall.call();
319         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
320
321     } else {
322         linkSlowCase(iter);
323
324         if (supportsFloatingPoint()) {
325 #if USE(JSVALUE64)
326             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
327             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
328             Jump fail3 = emitJumpIfImmediateInteger(regT1);
329             addPtr(tagTypeNumberRegister, regT0);
330             addPtr(tagTypeNumberRegister, regT1);
331             movePtrToDouble(regT0, fpRegT0);
332             movePtrToDouble(regT1, fpRegT1);
333 #else
334             Jump fail1;
335             if (!m_codeBlock->isKnownNotImmediate(op1))
336                 fail1 = emitJumpIfNotJSCell(regT0);
337
338             Jump fail2;
339             if (!m_codeBlock->isKnownNotImmediate(op2))
340                 fail2 = emitJumpIfNotJSCell(regT1);
341
342             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
343             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
344             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
345             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
346 #endif
347
348             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
349
350             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
351
352 #if USE(JSVALUE64)
353             fail1.link(this);
354             fail2.link(this);
355             fail3.link(this);
356 #else
357             if (!m_codeBlock->isKnownNotImmediate(op1))
358                 fail1.link(this);
359             if (!m_codeBlock->isKnownNotImmediate(op2))
360                 fail2.link(this);
361             fail3.link(this);
362             fail4.link(this);
363 #endif
364         }
365
366         linkSlowCase(iter);
367         JITStubCall stubCall(this, cti_op_jless);
368         stubCall.addArgument(regT0);
369         stubCall.addArgument(regT1);
370         stubCall.call();
371         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
372     }
373 }
374
375 void JIT::emit_op_jless(Instruction* currentInstruction)
376 {
377     unsigned op1 = currentInstruction[1].u.operand;
378     unsigned op2 = currentInstruction[2].u.operand;
379     unsigned target = currentInstruction[3].u.operand;
380
381     // We generate inline code for the following cases in the fast path:
382     // - int immediate to constant int immediate
383     // - constant int immediate to int immediate
384     // - int immediate to int immediate
385
386     if (isOperandConstantImmediateInt(op2)) {
387         emitGetVirtualRegister(op1, regT0);
388         emitJumpSlowCaseIfNotImmediateInteger(regT0);
389 #if USE(JSVALUE64)
390         int32_t op2imm = getConstantOperandImmediateInt(op2);
391 #else
392         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
393 #endif
394         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
395     } else if (isOperandConstantImmediateInt(op1)) {
396         emitGetVirtualRegister(op2, regT1);
397         emitJumpSlowCaseIfNotImmediateInteger(regT1);
398 #if USE(JSVALUE64)
399         int32_t op1imm = getConstantOperandImmediateInt(op1);
400 #else
401         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
402 #endif
403         addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
404     } else {
405         emitGetVirtualRegisters(op1, regT0, op2, regT1);
406         emitJumpSlowCaseIfNotImmediateInteger(regT0);
407         emitJumpSlowCaseIfNotImmediateInteger(regT1);
408
409         addJump(branch32(LessThan, regT0, regT1), target);
410     }
411 }
412
413 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
414 {
415     unsigned op1 = currentInstruction[1].u.operand;
416     unsigned op2 = currentInstruction[2].u.operand;
417     unsigned target = currentInstruction[3].u.operand;
418
419     // We generate inline code for the following cases in the slow path:
420     // - floating-point number to constant int immediate
421     // - constant int immediate to floating-point number
422     // - floating-point number to floating-point number.
423
424     if (isOperandConstantImmediateInt(op2)) {
425         linkSlowCase(iter);
426
427         if (supportsFloatingPoint()) {
428 #if USE(JSVALUE64)
429             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
430             addPtr(tagTypeNumberRegister, regT0);
431             movePtrToDouble(regT0, fpRegT0);
432 #else
433             Jump fail1;
434             if (!m_codeBlock->isKnownNotImmediate(op1))
435                 fail1 = emitJumpIfNotJSCell(regT0);
436
437             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
438             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
439 #endif
440
441             int32_t op2imm = getConstantOperand(op2).asInt32();
442
443             move(Imm32(op2imm), regT1);
444             convertInt32ToDouble(regT1, fpRegT1);
445
446             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
447
448             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
449
450 #if USE(JSVALUE64)
451             fail1.link(this);
452 #else
453             if (!m_codeBlock->isKnownNotImmediate(op1))
454                 fail1.link(this);
455             fail2.link(this);
456 #endif
457         }
458
459         JITStubCall stubCall(this, cti_op_jless);
460         stubCall.addArgument(regT0);
461         stubCall.addArgument(op2, regT2);
462         stubCall.call();
463         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
464
465     } else if (isOperandConstantImmediateInt(op1)) {
466         linkSlowCase(iter);
467
468         if (supportsFloatingPoint()) {
469 #if USE(JSVALUE64)
470             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
471             addPtr(tagTypeNumberRegister, regT1);
472             movePtrToDouble(regT1, fpRegT1);
473 #else
474             Jump fail1;
475             if (!m_codeBlock->isKnownNotImmediate(op2))
476                 fail1 = emitJumpIfNotJSCell(regT1);
477
478             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
479             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
480 #endif
481
482             int32_t op1imm = getConstantOperand(op1).asInt32();
483
484             move(Imm32(op1imm), regT0);
485             convertInt32ToDouble(regT0, fpRegT0);
486
487             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
488
489             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
490
491 #if USE(JSVALUE64)
492             fail1.link(this);
493 #else
494             if (!m_codeBlock->isKnownNotImmediate(op2))
495                 fail1.link(this);
496             fail2.link(this);
497 #endif
498         }
499
500         JITStubCall stubCall(this, cti_op_jless);
501         stubCall.addArgument(op1, regT2);
502         stubCall.addArgument(regT1);
503         stubCall.call();
504         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
505
506     } else {
507         linkSlowCase(iter);
508
509         if (supportsFloatingPoint()) {
510 #if USE(JSVALUE64)
511             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
512             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
513             Jump fail3 = emitJumpIfImmediateInteger(regT1);
514             addPtr(tagTypeNumberRegister, regT0);
515             addPtr(tagTypeNumberRegister, regT1);
516             movePtrToDouble(regT0, fpRegT0);
517             movePtrToDouble(regT1, fpRegT1);
518 #else
519             Jump fail1;
520             if (!m_codeBlock->isKnownNotImmediate(op1))
521                 fail1 = emitJumpIfNotJSCell(regT0);
522
523             Jump fail2;
524             if (!m_codeBlock->isKnownNotImmediate(op2))
525                 fail2 = emitJumpIfNotJSCell(regT1);
526
527             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
528             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
529             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
530             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
531 #endif
532
533             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
534
535             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
536
537 #if USE(JSVALUE64)
538             fail1.link(this);
539             fail2.link(this);
540             fail3.link(this);
541 #else
542             if (!m_codeBlock->isKnownNotImmediate(op1))
543                 fail1.link(this);
544             if (!m_codeBlock->isKnownNotImmediate(op2))
545                 fail2.link(this);
546             fail3.link(this);
547             fail4.link(this);
548 #endif
549         }
550
551         linkSlowCase(iter);
552         JITStubCall stubCall(this, cti_op_jless);
553         stubCall.addArgument(regT0);
554         stubCall.addArgument(regT1);
555         stubCall.call();
556         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
557     }
558 }
559
560 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
561 {
562     unsigned op1 = currentInstruction[1].u.operand;
563     unsigned op2 = currentInstruction[2].u.operand;
564     unsigned target = currentInstruction[3].u.operand;
565
566     // We generate inline code for the following cases in the fast path:
567     // - int immediate to constant int immediate
568     // - constant int immediate to int immediate
569     // - int immediate to int immediate
570
571     if (isOperandConstantImmediateInt(op2)) {
572         emitGetVirtualRegister(op1, regT0);
573         emitJumpSlowCaseIfNotImmediateInteger(regT0);
574 #if USE(JSVALUE64)
575         int32_t op2imm = getConstantOperandImmediateInt(op2);
576 #else
577         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
578 #endif
579         addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target);
580     } else if (isOperandConstantImmediateInt(op1)) {
581         emitGetVirtualRegister(op2, regT1);
582         emitJumpSlowCaseIfNotImmediateInteger(regT1);
583 #if USE(JSVALUE64)
584         int32_t op1imm = getConstantOperandImmediateInt(op1);
585 #else
586         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
587 #endif
588         addJump(branch32(LessThan, regT1, Imm32(op1imm)), target);
589     } else {
590         emitGetVirtualRegisters(op1, regT0, op2, regT1);
591         emitJumpSlowCaseIfNotImmediateInteger(regT0);
592         emitJumpSlowCaseIfNotImmediateInteger(regT1);
593
594         addJump(branch32(GreaterThan, regT0, regT1), target);
595     }
596 }
597
598 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
599 {
600     unsigned op1 = currentInstruction[1].u.operand;
601     unsigned op2 = currentInstruction[2].u.operand;
602     unsigned target = currentInstruction[3].u.operand;
603
604     // We generate inline code for the following cases in the slow path:
605     // - floating-point number to constant int immediate
606     // - constant int immediate to floating-point number
607     // - floating-point number to floating-point number.
608
609     if (isOperandConstantImmediateInt(op2)) {
610         linkSlowCase(iter);
611
612         if (supportsFloatingPoint()) {
613 #if USE(JSVALUE64)
614             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
615             addPtr(tagTypeNumberRegister, regT0);
616             movePtrToDouble(regT0, fpRegT0);
617 #else
618             Jump fail1;
619             if (!m_codeBlock->isKnownNotImmediate(op1))
620                 fail1 = emitJumpIfNotJSCell(regT0);
621
622             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
623             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
624 #endif
625
626             int32_t op2imm = getConstantOperand(op2).asInt32();;
627
628             move(Imm32(op2imm), regT1);
629             convertInt32ToDouble(regT1, fpRegT1);
630
631             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
632
633             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
634
635 #if USE(JSVALUE64)
636             fail1.link(this);
637 #else
638             if (!m_codeBlock->isKnownNotImmediate(op1))
639                 fail1.link(this);
640             fail2.link(this);
641 #endif
642         }
643
644         JITStubCall stubCall(this, cti_op_jlesseq);
645         stubCall.addArgument(regT0);
646         stubCall.addArgument(op2, regT2);
647         stubCall.call();
648         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
649
650     } else if (isOperandConstantImmediateInt(op1)) {
651         linkSlowCase(iter);
652
653         if (supportsFloatingPoint()) {
654 #if USE(JSVALUE64)
655             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
656             addPtr(tagTypeNumberRegister, regT1);
657             movePtrToDouble(regT1, fpRegT1);
658 #else
659             Jump fail1;
660             if (!m_codeBlock->isKnownNotImmediate(op2))
661                 fail1 = emitJumpIfNotJSCell(regT1);
662
663             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
664             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
665 #endif
666
667             int32_t op1imm = getConstantOperand(op1).asInt32();;
668
669             move(Imm32(op1imm), regT0);
670             convertInt32ToDouble(regT0, fpRegT0);
671
672             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
673
674             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
675
676 #if USE(JSVALUE64)
677             fail1.link(this);
678 #else
679             if (!m_codeBlock->isKnownNotImmediate(op2))
680                 fail1.link(this);
681             fail2.link(this);
682 #endif
683         }
684
685         JITStubCall stubCall(this, cti_op_jlesseq);
686         stubCall.addArgument(op1, regT2);
687         stubCall.addArgument(regT1);
688         stubCall.call();
689         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
690
691     } else {
692         linkSlowCase(iter);
693
694         if (supportsFloatingPoint()) {
695 #if USE(JSVALUE64)
696             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
697             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
698             Jump fail3 = emitJumpIfImmediateInteger(regT1);
699             addPtr(tagTypeNumberRegister, regT0);
700             addPtr(tagTypeNumberRegister, regT1);
701             movePtrToDouble(regT0, fpRegT0);
702             movePtrToDouble(regT1, fpRegT1);
703 #else
704             Jump fail1;
705             if (!m_codeBlock->isKnownNotImmediate(op1))
706                 fail1 = emitJumpIfNotJSCell(regT0);
707
708             Jump fail2;
709             if (!m_codeBlock->isKnownNotImmediate(op2))
710                 fail2 = emitJumpIfNotJSCell(regT1);
711
712             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
713             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
714             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
715             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
716 #endif
717
718             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
719
720             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
721
722 #if USE(JSVALUE64)
723             fail1.link(this);
724             fail2.link(this);
725             fail3.link(this);
726 #else
727             if (!m_codeBlock->isKnownNotImmediate(op1))
728                 fail1.link(this);
729             if (!m_codeBlock->isKnownNotImmediate(op2))
730                 fail2.link(this);
731             fail3.link(this);
732             fail4.link(this);
733 #endif
734         }
735
736         linkSlowCase(iter);
737         JITStubCall stubCall(this, cti_op_jlesseq);
738         stubCall.addArgument(regT0);
739         stubCall.addArgument(regT1);
740         stubCall.call();
741         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
742     }
743 }
744
745 void JIT::emit_op_bitand(Instruction* currentInstruction)
746 {
747     unsigned result = currentInstruction[1].u.operand;
748     unsigned op1 = currentInstruction[2].u.operand;
749     unsigned op2 = currentInstruction[3].u.operand;
750
751     if (isOperandConstantImmediateInt(op1)) {
752         emitGetVirtualRegister(op2, regT0);
753         emitJumpSlowCaseIfNotImmediateInteger(regT0);
754 #if USE(JSVALUE64)
755         int32_t imm = getConstantOperandImmediateInt(op1);
756         andPtr(Imm32(imm), regT0);
757         if (imm >= 0)
758             emitFastArithIntToImmNoCheck(regT0, regT0);
759 #else
760         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);
761 #endif
762     } else if (isOperandConstantImmediateInt(op2)) {
763         emitGetVirtualRegister(op1, regT0);
764         emitJumpSlowCaseIfNotImmediateInteger(regT0);
765 #if USE(JSVALUE64)
766         int32_t imm = getConstantOperandImmediateInt(op2);
767         andPtr(Imm32(imm), regT0);
768         if (imm >= 0)
769             emitFastArithIntToImmNoCheck(regT0, regT0);
770 #else
771         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);
772 #endif
773     } else {
774         emitGetVirtualRegisters(op1, regT0, op2, regT1);
775         andPtr(regT1, regT0);
776         emitJumpSlowCaseIfNotImmediateInteger(regT0);
777     }
778     emitPutVirtualRegister(result);
779 }
780
781 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
782 {
783     unsigned result = currentInstruction[1].u.operand;
784     unsigned op1 = currentInstruction[2].u.operand;
785     unsigned op2 = currentInstruction[3].u.operand;
786
787     linkSlowCase(iter);
788     if (isOperandConstantImmediateInt(op1)) {
789         JITStubCall stubCall(this, cti_op_bitand);
790         stubCall.addArgument(op1, regT2);
791         stubCall.addArgument(regT0);
792         stubCall.call(result);
793     } else if (isOperandConstantImmediateInt(op2)) {
794         JITStubCall stubCall(this, cti_op_bitand);
795         stubCall.addArgument(regT0);
796         stubCall.addArgument(op2, regT2);
797         stubCall.call(result);
798     } else {
799         JITStubCall stubCall(this, cti_op_bitand);
800         stubCall.addArgument(op1, regT2);
801         stubCall.addArgument(regT1);
802         stubCall.call(result);
803     }
804 }
805
806 void JIT::emit_op_post_inc(Instruction* currentInstruction)
807 {
808     unsigned result = currentInstruction[1].u.operand;
809     unsigned srcDst = currentInstruction[2].u.operand;
810
811     emitGetVirtualRegister(srcDst, regT0);
812     move(regT0, regT1);
813     emitJumpSlowCaseIfNotImmediateInteger(regT0);
814 #if USE(JSVALUE64)
815     addSlowCase(branchAdd32(Overflow, Imm32(1), regT1));
816     emitFastArithIntToImmNoCheck(regT1, regT1);
817 #else
818     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
819     signExtend32ToPtr(regT1, regT1);
820 #endif
821     emitPutVirtualRegister(srcDst, regT1);
822     emitPutVirtualRegister(result);
823 }
824
825 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
826 {
827     unsigned result = currentInstruction[1].u.operand;
828     unsigned srcDst = currentInstruction[2].u.operand;
829
830     linkSlowCase(iter);
831     linkSlowCase(iter);
832     JITStubCall stubCall(this, cti_op_post_inc);
833     stubCall.addArgument(regT0);
834     stubCall.addArgument(Imm32(srcDst));
835     stubCall.call(result);
836 }
837
838 void JIT::emit_op_post_dec(Instruction* currentInstruction)
839 {
840     unsigned result = currentInstruction[1].u.operand;
841     unsigned srcDst = currentInstruction[2].u.operand;
842
843     emitGetVirtualRegister(srcDst, regT0);
844     move(regT0, regT1);
845     emitJumpSlowCaseIfNotImmediateInteger(regT0);
846 #if USE(JSVALUE64)
847     addSlowCase(branchSub32(Zero, Imm32(1), regT1));
848     emitFastArithIntToImmNoCheck(regT1, regT1);
849 #else
850     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
851     signExtend32ToPtr(regT1, regT1);
852 #endif
853     emitPutVirtualRegister(srcDst, regT1);
854     emitPutVirtualRegister(result);
855 }
856
857 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
858 {
859     unsigned result = currentInstruction[1].u.operand;
860     unsigned srcDst = currentInstruction[2].u.operand;
861
862     linkSlowCase(iter);
863     linkSlowCase(iter);
864     JITStubCall stubCall(this, cti_op_post_dec);
865     stubCall.addArgument(regT0);
866     stubCall.addArgument(Imm32(srcDst));
867     stubCall.call(result);
868 }
869
870 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
871 {
872     unsigned srcDst = currentInstruction[1].u.operand;
873
874     emitGetVirtualRegister(srcDst, regT0);
875     emitJumpSlowCaseIfNotImmediateInteger(regT0);
876 #if USE(JSVALUE64)
877     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
878     emitFastArithIntToImmNoCheck(regT0, regT0);
879 #else
880     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
881     signExtend32ToPtr(regT0, regT0);
882 #endif
883     emitPutVirtualRegister(srcDst);
884 }
885
886 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
887 {
888     unsigned srcDst = currentInstruction[1].u.operand;
889
890     Jump notImm = getSlowCase(iter);
891     linkSlowCase(iter);
892     emitGetVirtualRegister(srcDst, regT0);
893     notImm.link(this);
894     JITStubCall stubCall(this, cti_op_pre_inc);
895     stubCall.addArgument(regT0);
896     stubCall.call(srcDst);
897 }
898
899 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
900 {
901     unsigned srcDst = currentInstruction[1].u.operand;
902
903     emitGetVirtualRegister(srcDst, regT0);
904     emitJumpSlowCaseIfNotImmediateInteger(regT0);
905 #if USE(JSVALUE64)
906     addSlowCase(branchSub32(Zero, Imm32(1), regT0));
907     emitFastArithIntToImmNoCheck(regT0, regT0);
908 #else
909     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
910     signExtend32ToPtr(regT0, regT0);
911 #endif
912     emitPutVirtualRegister(srcDst);
913 }
914
915 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
916 {
917     unsigned srcDst = currentInstruction[1].u.operand;
918
919     Jump notImm = getSlowCase(iter);
920     linkSlowCase(iter);
921     emitGetVirtualRegister(srcDst, regT0);
922     notImm.link(this);
923     JITStubCall stubCall(this, cti_op_pre_dec);
924     stubCall.addArgument(regT0);
925     stubCall.call(srcDst);
926 }
927
928 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
929
930 #if CPU(X86) || CPU(X86_64)
931
932 void JIT::emit_op_mod(Instruction* currentInstruction)
933 {
934     unsigned result = currentInstruction[1].u.operand;
935     unsigned op1 = currentInstruction[2].u.operand;
936     unsigned op2 = currentInstruction[3].u.operand;
937
938     emitGetVirtualRegisters(op1, X86Registers::eax, op2, X86Registers::ecx);
939     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax);
940     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx);
941 #if USE(JSVALUE64)
942     addSlowCase(branchPtr(Equal, X86Registers::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
943     m_assembler.cdq();
944     m_assembler.idivl_r(X86Registers::ecx);
945 #else
946     emitFastArithDeTagImmediate(X86Registers::eax);
947     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx));
948     m_assembler.cdq();
949     m_assembler.idivl_r(X86Registers::ecx);
950     signExtend32ToPtr(X86Registers::edx, X86Registers::edx);
951 #endif
952     emitFastArithReTagImmediate(X86Registers::edx, X86Registers::eax);
953     emitPutVirtualRegister(result);
954 }
955
956 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
957 {
958     unsigned result = currentInstruction[1].u.operand;
959
960 #if USE(JSVALUE64)
961     linkSlowCase(iter);
962     linkSlowCase(iter);
963     linkSlowCase(iter);
964 #else
965     Jump notImm1 = getSlowCase(iter);
966     Jump notImm2 = getSlowCase(iter);
967     linkSlowCase(iter);
968     emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax);
969     emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx);
970     notImm1.link(this);
971     notImm2.link(this);
972 #endif
973     JITStubCall stubCall(this, cti_op_mod);
974     stubCall.addArgument(X86Registers::eax);
975     stubCall.addArgument(X86Registers::ecx);
976     stubCall.call(result);
977 }
978
979 #else // CPU(X86) || CPU(X86_64)
980
981 void JIT::emit_op_mod(Instruction* currentInstruction)
982 {
983     unsigned result = currentInstruction[1].u.operand;
984     unsigned op1 = currentInstruction[2].u.operand;
985     unsigned op2 = currentInstruction[3].u.operand;
986
987 #if ENABLE(JIT_OPTIMIZE_MOD)
988     emitGetVirtualRegisters(op1, regT0, op2, regT2);
989     emitJumpSlowCaseIfNotImmediateInteger(regT0);
990     emitJumpSlowCaseIfNotImmediateInteger(regT2);
991
992     addSlowCase(branch32(Equal, regT2, Imm32(1)));
993
994     emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
995
996     emitPutVirtualRegister(result, regT0);
997 #else
998     JITStubCall stubCall(this, cti_op_mod);
999     stubCall.addArgument(op1, regT2);
1000     stubCall.addArgument(op2, regT2);
1001     stubCall.call(result);
1002 #endif
1003 }
1004
1005 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1006 {
1007 #if ENABLE(JIT_OPTIMIZE_MOD)
1008     unsigned result = currentInstruction[1].u.operand;
1009     unsigned op1 = currentInstruction[2].u.operand;
1010     unsigned op2 = currentInstruction[3].u.operand;
1011     linkSlowCase(iter);
1012     linkSlowCase(iter);
1013     linkSlowCase(iter);
1014     JITStubCall stubCall(this, cti_op_mod);
1015     stubCall.addArgument(op1, regT2);
1016     stubCall.addArgument(op2, regT2);
1017     stubCall.call(result);
1018 #else
1019     ASSERT_NOT_REACHED();
1020 #endif
1021 }
1022
1023 #endif // CPU(X86) || CPU(X86_64)
1024
1025 /* ------------------------------ END: OP_MOD ------------------------------ */
1026
1027 #if USE(JSVALUE64)
1028
1029 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
1030
1031 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
1032 {
1033     emitGetVirtualRegisters(op1, regT0, op2, regT1);
1034     emitJumpSlowCaseIfNotImmediateInteger(regT0);
1035     emitJumpSlowCaseIfNotImmediateInteger(regT1);
1036     if (opcodeID == op_add)
1037         addSlowCase(branchAdd32(Overflow, regT1, regT0));
1038     else if (opcodeID == op_sub)
1039         addSlowCase(branchSub32(Overflow, regT1, regT0));
1040     else {
1041         ASSERT(opcodeID == op_mul);
1042         addSlowCase(branchMul32(Overflow, regT1, regT0));
1043         addSlowCase(branchTest32(Zero, regT0));
1044     }
1045     emitFastArithIntToImmNoCheck(regT0, regT0);
1046 }
1047
1048 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
1049 {
1050     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
1051     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
1052
1053     Jump notImm1;
1054     Jump notImm2;
1055     if (op1HasImmediateIntFastCase) {
1056         notImm2 = getSlowCase(iter);
1057     } else if (op2HasImmediateIntFastCase) {
1058         notImm1 = getSlowCase(iter);
1059     } else {
1060         notImm1 = getSlowCase(iter);
1061         notImm2 = getSlowCase(iter);
1062     }
1063
1064     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
1065     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
1066         linkSlowCase(iter);
1067     emitGetVirtualRegister(op1, regT0);
1068
1069     Label stubFunctionCall(this);
1070     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
1071     if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) {
1072         emitGetVirtualRegister(op1, regT0);
1073         emitGetVirtualRegister(op2, regT1);
1074     }
1075     stubCall.addArgument(regT0);
1076     stubCall.addArgument(regT1);
1077     stubCall.call(result);
1078     Jump end = jump();
1079
1080     if (op1HasImmediateIntFastCase) {
1081         notImm2.link(this);
1082         if (!types.second().definitelyIsNumber())
1083             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1084         emitGetVirtualRegister(op1, regT1);
1085         convertInt32ToDouble(regT1, fpRegT1);
1086         addPtr(tagTypeNumberRegister, regT0);
1087         movePtrToDouble(regT0, fpRegT2);
1088     } else if (op2HasImmediateIntFastCase) {
1089         notImm1.link(this);
1090         if (!types.first().definitelyIsNumber())
1091             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1092         emitGetVirtualRegister(op2, regT1);
1093         convertInt32ToDouble(regT1, fpRegT1);
1094         addPtr(tagTypeNumberRegister, regT0);
1095         movePtrToDouble(regT0, fpRegT2);
1096     } else {
1097         // if we get here, eax is not an int32, edx not yet checked.
1098         notImm1.link(this);
1099         if (!types.first().definitelyIsNumber())
1100             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1101         if (!types.second().definitelyIsNumber())
1102             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
1103         addPtr(tagTypeNumberRegister, regT0);
1104         movePtrToDouble(regT0, fpRegT1);
1105         Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
1106         convertInt32ToDouble(regT1, fpRegT2);
1107         Jump op2wasInteger = jump();
1108
1109         // if we get here, eax IS an int32, edx is not.
1110         notImm2.link(this);
1111         if (!types.second().definitelyIsNumber())
1112             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
1113         convertInt32ToDouble(regT0, fpRegT1);
1114         op2isDouble.link(this);
1115         addPtr(tagTypeNumberRegister, regT1);
1116         movePtrToDouble(regT1, fpRegT2);
1117         op2wasInteger.link(this);
1118     }
1119
1120     if (opcodeID == op_add)
1121         addDouble(fpRegT2, fpRegT1);
1122     else if (opcodeID == op_sub)
1123         subDouble(fpRegT2, fpRegT1);
1124     else if (opcodeID == op_mul)
1125         mulDouble(fpRegT2, fpRegT1);
1126     else {
1127         ASSERT(opcodeID == op_div);
1128         divDouble(fpRegT2, fpRegT1);
1129     }
1130     moveDoubleToPtr(fpRegT1, regT0);
1131     subPtr(tagTypeNumberRegister, regT0);
1132     emitPutVirtualRegister(result, regT0);
1133
1134     end.link(this);
1135 }
1136
1137 void JIT::emit_op_add(Instruction* currentInstruction)
1138 {
1139     unsigned result = currentInstruction[1].u.operand;
1140     unsigned op1 = currentInstruction[2].u.operand;
1141     unsigned op2 = currentInstruction[3].u.operand;
1142     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1143
1144     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
1145         JITStubCall stubCall(this, cti_op_add);
1146         stubCall.addArgument(op1, regT2);
1147         stubCall.addArgument(op2, regT2);
1148         stubCall.call(result);
1149         return;
1150     }
1151
1152     if (isOperandConstantImmediateInt(op1)) {
1153         emitGetVirtualRegister(op2, regT0);
1154         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1155         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
1156         emitFastArithIntToImmNoCheck(regT0, regT0);
1157     } else if (isOperandConstantImmediateInt(op2)) {
1158         emitGetVirtualRegister(op1, regT0);
1159         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1160         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
1161         emitFastArithIntToImmNoCheck(regT0, regT0);
1162     } else
1163         compileBinaryArithOp(op_add, result, op1, op2, types);
1164
1165     emitPutVirtualRegister(result);
1166 }
1167
1168 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1169 {
1170     unsigned result = currentInstruction[1].u.operand;
1171     unsigned op1 = currentInstruction[2].u.operand;
1172     unsigned op2 = currentInstruction[3].u.operand;
1173     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1174
1175     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
1176         return;
1177
1178     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
1179     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
1180     compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
1181 }
1182
1183 void JIT::emit_op_mul(Instruction* currentInstruction)
1184 {
1185     unsigned result = currentInstruction[1].u.operand;
1186     unsigned op1 = currentInstruction[2].u.operand;
1187     unsigned op2 = currentInstruction[3].u.operand;
1188     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1189
1190     // For now, only plant a fast int case if the constant operand is greater than zero.
1191     int32_t value;
1192     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
1193         emitGetVirtualRegister(op2, regT0);
1194         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1195         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1196         emitFastArithReTagImmediate(regT0, regT0);
1197     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
1198         emitGetVirtualRegister(op1, regT0);
1199         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1200         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1201         emitFastArithReTagImmediate(regT0, regT0);
1202     } else
1203         compileBinaryArithOp(op_mul, result, op1, op2, types);
1204
1205     emitPutVirtualRegister(result);
1206 }
1207
1208 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1209 {
1210     unsigned result = currentInstruction[1].u.operand;
1211     unsigned op1 = currentInstruction[2].u.operand;
1212     unsigned op2 = currentInstruction[3].u.operand;
1213     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1214
1215     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
1216     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
1217     compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
1218 }
1219
1220 void JIT::emit_op_div(Instruction* currentInstruction)
1221 {
1222     unsigned dst = currentInstruction[1].u.operand;
1223     unsigned op1 = currentInstruction[2].u.operand;
1224     unsigned op2 = currentInstruction[3].u.operand;
1225     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1226
1227     if (isOperandConstantImmediateDouble(op1)) {
1228         emitGetVirtualRegister(op1, regT0);
1229         addPtr(tagTypeNumberRegister, regT0);
1230         movePtrToDouble(regT0, fpRegT0);
1231     } else if (isOperandConstantImmediateInt(op1)) {
1232         emitLoadInt32ToDouble(op1, fpRegT0);
1233     } else {
1234         emitGetVirtualRegister(op1, regT0);
1235         if (!types.first().definitelyIsNumber())
1236             emitJumpSlowCaseIfNotImmediateNumber(regT0);
1237         Jump notInt = emitJumpIfNotImmediateInteger(regT0);
1238         convertInt32ToDouble(regT0, fpRegT0);
1239         Jump skipDoubleLoad = jump();
1240         notInt.link(this);
1241         addPtr(tagTypeNumberRegister, regT0);
1242         movePtrToDouble(regT0, fpRegT0);
1243         skipDoubleLoad.link(this);
1244     }
1245
1246     if (isOperandConstantImmediateDouble(op2)) {
1247         emitGetVirtualRegister(op2, regT1);
1248         addPtr(tagTypeNumberRegister, regT1);
1249         movePtrToDouble(regT1, fpRegT1);
1250     } else if (isOperandConstantImmediateInt(op2)) {
1251         emitLoadInt32ToDouble(op2, fpRegT1);
1252     } else {
1253         emitGetVirtualRegister(op2, regT1);
1254         if (!types.second().definitelyIsNumber())
1255             emitJumpSlowCaseIfNotImmediateNumber(regT1);
1256         Jump notInt = emitJumpIfNotImmediateInteger(regT1);
1257         convertInt32ToDouble(regT1, fpRegT1);
1258         Jump skipDoubleLoad = jump();
1259         notInt.link(this);
1260         addPtr(tagTypeNumberRegister, regT1);
1261         movePtrToDouble(regT1, fpRegT1);
1262         skipDoubleLoad.link(this);
1263     }
1264     divDouble(fpRegT1, fpRegT0);
1265
1266     // Double result.
1267     moveDoubleToPtr(fpRegT0, regT0);
1268     subPtr(tagTypeNumberRegister, regT0);
1269
1270     emitPutVirtualRegister(dst, regT0);
1271 }
1272
1273 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1274 {
1275     unsigned result = currentInstruction[1].u.operand;
1276     unsigned op1 = currentInstruction[2].u.operand;
1277     unsigned op2 = currentInstruction[3].u.operand;
1278     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1279     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
1280 #ifndef NDEBUG
1281         breakpoint();
1282 #endif
1283         return;
1284     }
1285     if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
1286         if (!types.first().definitelyIsNumber())
1287             linkSlowCase(iter);
1288     }
1289     if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
1290         if (!types.second().definitelyIsNumber())
1291             linkSlowCase(iter);
1292     }
1293     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1294     JITStubCall stubCall(this, cti_op_div);
1295     stubCall.addArgument(op1, regT2);
1296     stubCall.addArgument(op2, regT2);
1297     stubCall.call(result);
1298 }
1299
1300 void JIT::emit_op_sub(Instruction* currentInstruction)
1301 {
1302     unsigned result = currentInstruction[1].u.operand;
1303     unsigned op1 = currentInstruction[2].u.operand;
1304     unsigned op2 = currentInstruction[3].u.operand;
1305     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1306
1307     compileBinaryArithOp(op_sub, result, op1, op2, types);
1308     emitPutVirtualRegister(result);
1309 }
1310
1311 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1312 {
1313     unsigned result = currentInstruction[1].u.operand;
1314     unsigned op1 = currentInstruction[2].u.operand;
1315     unsigned op2 = currentInstruction[3].u.operand;
1316     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1317
1318     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
1319 }
1320
1321 #else // USE(JSVALUE64)
1322
1323 /* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
1324
1325 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
1326 {
1327     Structure* numberStructure = m_globalData->numberStructure.get();
1328     Jump wasJSNumberCell1;
1329     Jump wasJSNumberCell2;
1330
1331     emitGetVirtualRegisters(src1, regT0, src2, regT1);
1332
1333     if (types.second().isReusable() && supportsFloatingPoint()) {
1334         ASSERT(types.second().mightBeNumber());
1335
1336         // Check op2 is a number
1337         Jump op2imm = emitJumpIfImmediateInteger(regT1);
1338         if (!types.second().definitelyIsNumber()) {
1339             emitJumpSlowCaseIfNotJSCell(regT1, src2);
1340             addSlowCase(checkStructure(regT1, numberStructure));
1341         }
1342
1343         // (1) In this case src2 is a reusable number cell.
1344         //     Slow case if src1 is not a number type.
1345         Jump op1imm = emitJumpIfImmediateInteger(regT0);
1346         if (!types.first().definitelyIsNumber()) {
1347             emitJumpSlowCaseIfNotJSCell(regT0, src1);
1348             addSlowCase(checkStructure(regT0, numberStructure));
1349         }
1350
1351         // (1a) if we get here, src1 is also a number cell
1352         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1353         Jump loadedDouble = jump();
1354         // (1b) if we get here, src1 is an immediate
1355         op1imm.link(this);
1356         emitFastArithImmToInt(regT0);
1357         convertInt32ToDouble(regT0, fpRegT0);
1358         // (1c)
1359         loadedDouble.link(this);
1360         if (opcodeID == op_add)
1361             addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1362         else if (opcodeID == op_sub)
1363             subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1364         else {
1365             ASSERT(opcodeID == op_mul);
1366             mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1367         }
1368
1369         // Store the result to the JSNumberCell and jump.
1370         storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)));
1371         move(regT1, regT0);
1372         emitPutVirtualRegister(dst);
1373         wasJSNumberCell2 = jump();
1374
1375         // (2) This handles cases where src2 is an immediate number.
1376         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
1377         op2imm.link(this);
1378         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1379     } else if (types.first().isReusable() && supportsFloatingPoint()) {
1380         ASSERT(types.first().mightBeNumber());
1381
1382         // Check op1 is a number
1383         Jump op1imm = emitJumpIfImmediateInteger(regT0);
1384         if (!types.first().definitelyIsNumber()) {
1385             emitJumpSlowCaseIfNotJSCell(regT0, src1);
1386             addSlowCase(checkStructure(regT0, numberStructure));
1387         }
1388
1389         // (1) In this case src1 is a reusable number cell.
1390         //     Slow case if src2 is not a number type.
1391         Jump op2imm = emitJumpIfImmediateInteger(regT1);
1392         if (!types.second().definitelyIsNumber()) {
1393             emitJumpSlowCaseIfNotJSCell(regT1, src2);
1394             addSlowCase(checkStructure(regT1, numberStructure));
1395         }
1396
1397         // (1a) if we get here, src2 is also a number cell
1398         loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1399         Jump loadedDouble = jump();
1400         // (1b) if we get here, src2 is an immediate
1401         op2imm.link(this);
1402         emitFastArithImmToInt(regT1);
1403         convertInt32ToDouble(regT1, fpRegT1);
1404         // (1c)
1405         loadedDouble.link(this);
1406         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1407         if (opcodeID == op_add)
1408             addDouble(fpRegT1, fpRegT0);
1409         else if (opcodeID == op_sub)
1410             subDouble(fpRegT1, fpRegT0);
1411         else {
1412             ASSERT(opcodeID == op_mul);
1413             mulDouble(fpRegT1, fpRegT0);
1414         }
1415         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
1416         emitPutVirtualRegister(dst);
1417
1418         // Store the result to the JSNumberCell and jump.
1419         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
1420         emitPutVirtualRegister(dst);
1421         wasJSNumberCell1 = jump();
1422
1423         // (2) This handles cases where src1 is an immediate number.
1424         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
1425         op1imm.link(this);
1426         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1427     } else
1428         emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
1429
1430     if (opcodeID == op_add) {
1431         emitFastArithDeTagImmediate(regT0);
1432         addSlowCase(branchAdd32(Overflow, regT1, regT0));
1433     } else  if (opcodeID == op_sub) {
1434         addSlowCase(branchSub32(Overflow, regT1, regT0));
1435         signExtend32ToPtr(regT0, regT0);
1436         emitFastArithReTagImmediate(regT0, regT0);
1437     } else {
1438         ASSERT(opcodeID == op_mul);
1439         // convert eax & edx from JSImmediates to ints, and check if either are zero
1440         emitFastArithImmToInt(regT1);
1441         Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0);
1442         Jump op2NonZero = branchTest32(NonZero, regT1);
1443         op1Zero.link(this);
1444         // if either input is zero, add the two together, and check if the result is < 0.
1445         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
1446         move(regT0, regT2);
1447         addSlowCase(branchAdd32(Signed, regT1, regT2));
1448         // Skip the above check if neither input is zero
1449         op2NonZero.link(this);
1450         addSlowCase(branchMul32(Overflow, regT1, regT0));
1451         signExtend32ToPtr(regT0, regT0);
1452         emitFastArithReTagImmediate(regT0, regT0);
1453     }
1454     emitPutVirtualRegister(dst);
1455
1456     if (types.second().isReusable() && supportsFloatingPoint())
1457         wasJSNumberCell2.link(this);
1458     else if (types.first().isReusable() && supportsFloatingPoint())
1459         wasJSNumberCell1.link(this);
1460 }
1461
1462 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
1463 {
1464     linkSlowCase(iter);
1465     if (types.second().isReusable() && supportsFloatingPoint()) {
1466         if (!types.first().definitelyIsNumber()) {
1467             linkSlowCaseIfNotJSCell(iter, src1);
1468             linkSlowCase(iter);
1469         }
1470         if (!types.second().definitelyIsNumber()) {
1471             linkSlowCaseIfNotJSCell(iter, src2);
1472             linkSlowCase(iter);
1473         }
1474     } else if (types.first().isReusable() && supportsFloatingPoint()) {
1475         if (!types.first().definitelyIsNumber()) {
1476             linkSlowCaseIfNotJSCell(iter, src1);
1477             linkSlowCase(iter);
1478         }
1479         if (!types.second().definitelyIsNumber()) {
1480             linkSlowCaseIfNotJSCell(iter, src2);
1481             linkSlowCase(iter);
1482         }
1483     }
1484     linkSlowCase(iter);
1485
1486     // additional entry point to handle -0 cases.
1487     if (opcodeID == op_mul)
1488         linkSlowCase(iter);
1489
1490     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
1491     stubCall.addArgument(src1, regT2);
1492     stubCall.addArgument(src2, regT2);
1493     stubCall.call(dst);
1494 }
1495
1496 void JIT::emit_op_add(Instruction* currentInstruction)
1497 {
1498     unsigned result = currentInstruction[1].u.operand;
1499     unsigned op1 = currentInstruction[2].u.operand;
1500     unsigned op2 = currentInstruction[3].u.operand;
1501     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1502
1503     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
1504         JITStubCall stubCall(this, cti_op_add);
1505         stubCall.addArgument(op1, regT2);
1506         stubCall.addArgument(op2, regT2);
1507         stubCall.call(result);
1508         return;
1509     }
1510
1511     if (isOperandConstantImmediateInt(op1)) {
1512         emitGetVirtualRegister(op2, regT0);
1513         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1514         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0));
1515         signExtend32ToPtr(regT0, regT0);
1516         emitPutVirtualRegister(result);
1517     } else if (isOperandConstantImmediateInt(op2)) {
1518         emitGetVirtualRegister(op1, regT0);
1519         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1520         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0));
1521         signExtend32ToPtr(regT0, regT0);
1522         emitPutVirtualRegister(result);
1523     } else {
1524         compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
1525     }
1526 }
1527
1528 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1529 {
1530     unsigned result = currentInstruction[1].u.operand;
1531     unsigned op1 = currentInstruction[2].u.operand;
1532     unsigned op2 = currentInstruction[3].u.operand;
1533
1534     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1535     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
1536         return;
1537
1538     if (isOperandConstantImmediateInt(op1)) {
1539         Jump notImm = getSlowCase(iter);
1540         linkSlowCase(iter);
1541         sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0);
1542         notImm.link(this);
1543         JITStubCall stubCall(this, cti_op_add);
1544         stubCall.addArgument(op1, regT2);
1545         stubCall.addArgument(regT0);
1546         stubCall.call(result);
1547     } else if (isOperandConstantImmediateInt(op2)) {
1548         Jump notImm = getSlowCase(iter);
1549         linkSlowCase(iter);
1550         sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0);
1551         notImm.link(this);
1552         JITStubCall stubCall(this, cti_op_add);
1553         stubCall.addArgument(regT0);
1554         stubCall.addArgument(op2, regT2);
1555         stubCall.call(result);
1556     } else {
1557         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1558         ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
1559         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
1560     }
1561 }
1562
1563 void JIT::emit_op_mul(Instruction* currentInstruction)
1564 {
1565     unsigned result = currentInstruction[1].u.operand;
1566     unsigned op1 = currentInstruction[2].u.operand;
1567     unsigned op2 = currentInstruction[3].u.operand;
1568
1569     // For now, only plant a fast int case if the constant operand is greater than zero.
1570     int32_t value;
1571     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
1572         emitGetVirtualRegister(op2, regT0);
1573         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1574         emitFastArithDeTagImmediate(regT0);
1575         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1576         signExtend32ToPtr(regT0, regT0);
1577         emitFastArithReTagImmediate(regT0, regT0);
1578         emitPutVirtualRegister(result);
1579     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
1580         emitGetVirtualRegister(op1, regT0);
1581         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1582         emitFastArithDeTagImmediate(regT0);
1583         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1584         signExtend32ToPtr(regT0, regT0);
1585         emitFastArithReTagImmediate(regT0, regT0);
1586         emitPutVirtualRegister(result);
1587     } else
1588         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
1589 }
1590
1591 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1592 {
1593     unsigned result = currentInstruction[1].u.operand;
1594     unsigned op1 = currentInstruction[2].u.operand;
1595     unsigned op2 = currentInstruction[3].u.operand;
1596
1597     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
1598         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
1599         linkSlowCase(iter);
1600         linkSlowCase(iter);
1601         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1602         JITStubCall stubCall(this, cti_op_mul);
1603         stubCall.addArgument(op1, regT2);
1604         stubCall.addArgument(op2, regT2);
1605         stubCall.call(result);
1606     } else
1607         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
1608 }
1609
1610 void JIT::emit_op_sub(Instruction* currentInstruction)
1611 {
1612     compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
1613 }
1614
1615 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1616 {
1617     compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
1618 }
1619
1620 #endif // USE(JSVALUE64)
1621
1622 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
1623
1624 #endif // !USE(JSVALUE32_64)
1625
1626 } // namespace JSC
1627
1628 #endif // ENABLE(JIT)