• 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 "JSArray.h"
34 #include "JSFunction.h"
35 #include "Interpreter.h"
36 #include "ResultType.h"
37 #include "SamplingTool.h"
38 
39 #ifndef NDEBUG
40 #include <stdio.h>
41 #endif
42 
43 #define __ m_assembler.
44 
45 using namespace std;
46 
47 namespace JSC {
48 
compileFastArith_op_lshift(unsigned result,unsigned op1,unsigned op2)49 void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2)
50 {
51     emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
52     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
53     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
54     emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
55     emitFastArithImmToInt(X86::eax);
56     emitFastArithImmToInt(X86::ecx);
57 #if !PLATFORM(X86)
58     // Mask with 0x1f as per ecma-262 11.7.2 step 7.
59     // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
60     and32(Imm32(0x1f), X86::ecx);
61 #endif
62     lshift32(X86::ecx, X86::eax);
63 #if !USE(ALTERNATE_JSIMMEDIATE)
64     addSlowCase(joAdd32(X86::eax, X86::eax));
65     signExtend32ToPtr(X86::eax, X86::eax);
66 #endif
67     emitFastArithReTagImmediate(X86::eax, X86::eax);
68     emitPutVirtualRegister(result);
69 }
compileFastArithSlow_op_lshift(unsigned result,unsigned op1,unsigned op2,Vector<SlowCaseEntry>::iterator & iter)70 void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
71 {
72 #if USE(ALTERNATE_JSIMMEDIATE)
73     UNUSED_PARAM(op1);
74     UNUSED_PARAM(op2);
75     linkSlowCase(iter);
76     linkSlowCase(iter);
77 #else
78     // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
79     Jump notImm1 = getSlowCase(iter);
80     Jump notImm2 = getSlowCase(iter);
81     linkSlowCase(iter);
82     emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
83     notImm1.link(this);
84     notImm2.link(this);
85 #endif
86     emitPutJITStubArg(X86::eax, 1);
87     emitPutJITStubArg(X86::ecx, 2);
88     emitCTICall(Interpreter::cti_op_lshift);
89     emitPutVirtualRegister(result);
90 }
91 
compileFastArith_op_rshift(unsigned result,unsigned op1,unsigned op2)92 void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2)
93 {
94     if (isOperandConstantImmediateInt(op2)) {
95         emitGetVirtualRegister(op1, X86::eax);
96         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
97         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
98 #if USE(ALTERNATE_JSIMMEDIATE)
99         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax);
100 #else
101         rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax);
102 #endif
103     } else {
104         emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
105         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
106         emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
107         emitFastArithImmToInt(X86::ecx);
108 #if !PLATFORM(X86)
109         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
110         // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
111         and32(Imm32(0x1f), X86::ecx);
112 #endif
113 #if USE(ALTERNATE_JSIMMEDIATE)
114         rshift32(X86::ecx, X86::eax);
115 #else
116         rshiftPtr(X86::ecx, X86::eax);
117 #endif
118     }
119 #if USE(ALTERNATE_JSIMMEDIATE)
120     emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
121 #else
122     orPtr(Imm32(JSImmediate::TagTypeNumber), X86::eax);
123 #endif
124     emitPutVirtualRegister(result);
125 }
compileFastArithSlow_op_rshift(unsigned result,unsigned,unsigned op2,Vector<SlowCaseEntry>::iterator & iter)126 void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
127 {
128     linkSlowCase(iter);
129     if (isOperandConstantImmediateInt(op2))
130         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
131     else {
132         linkSlowCase(iter);
133         emitPutJITStubArg(X86::ecx, 2);
134     }
135 
136     emitPutJITStubArg(X86::eax, 1);
137     emitCTICall(Interpreter::cti_op_rshift);
138     emitPutVirtualRegister(result);
139 }
140 
compileFastArith_op_bitand(unsigned result,unsigned op1,unsigned op2)141 void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2)
142 {
143     if (isOperandConstantImmediateInt(op1)) {
144         emitGetVirtualRegister(op2, X86::eax);
145         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
146 #if USE(ALTERNATE_JSIMMEDIATE)
147         int32_t imm = getConstantOperandImmediateInt(op1);
148         andPtr(Imm32(imm), X86::eax);
149         if (imm >= 0)
150             emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
151 #else
152         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax);
153 #endif
154     } else if (isOperandConstantImmediateInt(op2)) {
155         emitGetVirtualRegister(op1, X86::eax);
156         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
157 #if USE(ALTERNATE_JSIMMEDIATE)
158         int32_t imm = getConstantOperandImmediateInt(op2);
159         andPtr(Imm32(imm), X86::eax);
160         if (imm >= 0)
161             emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
162 #else
163         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax);
164 #endif
165     } else {
166         emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
167         andPtr(X86::edx, X86::eax);
168         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
169     }
170     emitPutVirtualRegister(result);
171 }
compileFastArithSlow_op_bitand(unsigned result,unsigned op1,unsigned op2,Vector<SlowCaseEntry>::iterator & iter)172 void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
173 {
174     linkSlowCase(iter);
175     if (isOperandConstantImmediateInt(op1)) {
176         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
177         emitPutJITStubArg(X86::eax, 2);
178     } else if (isOperandConstantImmediateInt(op2)) {
179         emitPutJITStubArg(X86::eax, 1);
180         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
181     } else {
182         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
183         emitPutJITStubArg(X86::edx, 2);
184     }
185     emitCTICall(Interpreter::cti_op_bitand);
186     emitPutVirtualRegister(result);
187 }
188 
compileFastArith_op_mod(unsigned result,unsigned op1,unsigned op2)189 void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2)
190 {
191     emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
192     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
193     emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
194 #if USE(ALTERNATE_JSIMMEDIATE)
195     addSlowCase(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(js0()))));
196     mod32(X86::ecx, X86::eax, X86::edx);
197 #else
198     emitFastArithDeTagImmediate(X86::eax);
199     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
200     mod32(X86::ecx, X86::eax, X86::edx);
201     signExtend32ToPtr(X86::edx, X86::edx);
202 #endif
203     emitFastArithReTagImmediate(X86::edx, X86::eax);
204     emitPutVirtualRegister(result);
205 }
compileFastArithSlow_op_mod(unsigned result,unsigned,unsigned,Vector<SlowCaseEntry>::iterator & iter)206 void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter)
207 {
208 #if USE(ALTERNATE_JSIMMEDIATE)
209     linkSlowCase(iter);
210     linkSlowCase(iter);
211     linkSlowCase(iter);
212 #else
213     Jump notImm1 = getSlowCase(iter);
214     Jump notImm2 = getSlowCase(iter);
215     linkSlowCase(iter);
216     emitFastArithReTagImmediate(X86::eax, X86::eax);
217     emitFastArithReTagImmediate(X86::ecx, X86::ecx);
218     notImm1.link(this);
219     notImm2.link(this);
220 #endif
221     emitPutJITStubArg(X86::eax, 1);
222     emitPutJITStubArg(X86::ecx, 2);
223     emitCTICall(Interpreter::cti_op_mod);
224     emitPutVirtualRegister(result);
225 }
226 
compileFastArith_op_post_inc(unsigned result,unsigned srcDst)227 void JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst)
228 {
229     emitGetVirtualRegister(srcDst, X86::eax);
230     move(X86::eax, X86::edx);
231     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
232 #if USE(ALTERNATE_JSIMMEDIATE)
233     addSlowCase(joAdd32(Imm32(1), X86::edx));
234     emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
235 #else
236     addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
237     signExtend32ToPtr(X86::edx, X86::edx);
238 #endif
239     emitPutVirtualRegister(srcDst, X86::edx);
240     emitPutVirtualRegister(result);
241 }
compileFastArithSlow_op_post_inc(unsigned result,unsigned srcDst,Vector<SlowCaseEntry>::iterator & iter)242 void JIT::compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
243 {
244     linkSlowCase(iter);
245     linkSlowCase(iter);
246     emitPutJITStubArg(X86::eax, 1);
247     emitCTICall(Interpreter::cti_op_post_inc);
248     emitPutVirtualRegister(srcDst, X86::edx);
249     emitPutVirtualRegister(result);
250 }
251 
compileFastArith_op_post_dec(unsigned result,unsigned srcDst)252 void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst)
253 {
254     emitGetVirtualRegister(srcDst, X86::eax);
255     move(X86::eax, X86::edx);
256     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
257 #if USE(ALTERNATE_JSIMMEDIATE)
258     addSlowCase(joSub32(Imm32(1), X86::edx));
259     emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
260 #else
261     addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
262     signExtend32ToPtr(X86::edx, X86::edx);
263 #endif
264     emitPutVirtualRegister(srcDst, X86::edx);
265     emitPutVirtualRegister(result);
266 }
compileFastArithSlow_op_post_dec(unsigned result,unsigned srcDst,Vector<SlowCaseEntry>::iterator & iter)267 void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
268 {
269     linkSlowCase(iter);
270     linkSlowCase(iter);
271     emitPutJITStubArg(X86::eax, 1);
272     emitCTICall(Interpreter::cti_op_post_dec);
273     emitPutVirtualRegister(srcDst, X86::edx);
274     emitPutVirtualRegister(result);
275 }
276 
compileFastArith_op_pre_inc(unsigned srcDst)277 void JIT::compileFastArith_op_pre_inc(unsigned srcDst)
278 {
279     emitGetVirtualRegister(srcDst, X86::eax);
280     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
281 #if USE(ALTERNATE_JSIMMEDIATE)
282     addSlowCase(joAdd32(Imm32(1), X86::eax));
283     emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
284 #else
285     addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
286     signExtend32ToPtr(X86::eax, X86::eax);
287 #endif
288     emitPutVirtualRegister(srcDst);
289 }
compileFastArithSlow_op_pre_inc(unsigned srcDst,Vector<SlowCaseEntry>::iterator & iter)290 void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
291 {
292     Jump notImm = getSlowCase(iter);
293     linkSlowCase(iter);
294     emitGetVirtualRegister(srcDst, X86::eax);
295     notImm.link(this);
296     emitPutJITStubArg(X86::eax, 1);
297     emitCTICall(Interpreter::cti_op_pre_inc);
298     emitPutVirtualRegister(srcDst);
299 }
300 
compileFastArith_op_pre_dec(unsigned srcDst)301 void JIT::compileFastArith_op_pre_dec(unsigned srcDst)
302 {
303     emitGetVirtualRegister(srcDst, X86::eax);
304     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
305 #if USE(ALTERNATE_JSIMMEDIATE)
306     addSlowCase(joSub32(Imm32(1), X86::eax));
307     emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
308 #else
309     addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
310     signExtend32ToPtr(X86::eax, X86::eax);
311 #endif
312     emitPutVirtualRegister(srcDst);
313 }
compileFastArithSlow_op_pre_dec(unsigned srcDst,Vector<SlowCaseEntry>::iterator & iter)314 void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
315 {
316     Jump notImm = getSlowCase(iter);
317     linkSlowCase(iter);
318     emitGetVirtualRegister(srcDst, X86::eax);
319     notImm.link(this);
320     emitPutJITStubArg(X86::eax, 1);
321     emitCTICall(Interpreter::cti_op_pre_dec);
322     emitPutVirtualRegister(srcDst);
323 }
324 
325 
326 #if !ENABLE(JIT_OPTIMIZE_ARITHMETIC)
327 
compileFastArith_op_add(Instruction * currentInstruction)328 void JIT::compileFastArith_op_add(Instruction* currentInstruction)
329 {
330     unsigned result = currentInstruction[1].u.operand;
331     unsigned op1 = currentInstruction[2].u.operand;
332     unsigned op2 = currentInstruction[3].u.operand;
333 
334     emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
335     emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
336     emitCTICall(Interpreter::cti_op_add);
337     emitPutVirtualRegister(result);
338 }
compileFastArithSlow_op_add(Instruction *,Vector<SlowCaseEntry>::iterator &)339 void JIT::compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&)
340 {
341     ASSERT_NOT_REACHED();
342 }
343 
compileFastArith_op_mul(Instruction * currentInstruction)344 void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
345 {
346     unsigned result = currentInstruction[1].u.operand;
347     unsigned op1 = currentInstruction[2].u.operand;
348     unsigned op2 = currentInstruction[3].u.operand;
349 
350     emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
351     emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
352     emitCTICall(Interpreter::cti_op_mul);
353     emitPutVirtualRegister(result);
354 }
compileFastArithSlow_op_mul(Instruction *,Vector<SlowCaseEntry>::iterator &)355 void JIT::compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&)
356 {
357     ASSERT_NOT_REACHED();
358 }
359 
compileFastArith_op_sub(Instruction * currentInstruction)360 void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
361 {
362     unsigned result = currentInstruction[1].u.operand;
363     unsigned op1 = currentInstruction[2].u.operand;
364     unsigned op2 = currentInstruction[3].u.operand;
365 
366     emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
367     emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
368     emitCTICall(Interpreter::cti_op_sub);
369     emitPutVirtualRegister(result);
370 }
compileFastArithSlow_op_sub(Instruction *,Vector<SlowCaseEntry>::iterator &)371 void JIT::compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&)
372 {
373     ASSERT_NOT_REACHED();
374 }
375 
376 #elif USE(ALTERNATE_JSIMMEDIATE) // *AND* ENABLE(JIT_OPTIMIZE_ARITHMETIC)
377 
compileBinaryArithOp(OpcodeID opcodeID,unsigned,unsigned op1,unsigned op2,OperandTypes)378 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
379 {
380     emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
381     emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
382     emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
383     if (opcodeID == op_add)
384         addSlowCase(joAdd32(X86::edx, X86::eax));
385     else if (opcodeID == op_sub)
386         addSlowCase(joSub32(X86::edx, X86::eax));
387     else {
388         ASSERT(opcodeID == op_mul);
389         addSlowCase(joMul32(X86::edx, X86::eax));
390         addSlowCase(jz32(X86::eax));
391     }
392     emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
393 }
394 
compileBinaryArithOpSlowCase(OpcodeID opcodeID,Vector<SlowCaseEntry>::iterator & iter,unsigned,unsigned op1,unsigned,OperandTypes types)395 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned, unsigned op1, unsigned, OperandTypes types)
396 {
397     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
398     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
399 
400     Jump notImm1 = getSlowCase(iter);
401     Jump notImm2 = getSlowCase(iter);
402 
403     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
404     if (opcodeID == op_mul) // op_mul has an extra slow case to handle 0 * negative number.
405         linkSlowCase(iter);
406     emitGetVirtualRegister(op1, X86::eax);
407 
408     Label stubFunctionCall(this);
409     emitPutJITStubArg(X86::eax, 1);
410     emitPutJITStubArg(X86::edx, 2);
411     if (opcodeID == op_add)
412         emitCTICall(Interpreter::cti_op_add);
413     else if (opcodeID == op_sub)
414         emitCTICall(Interpreter::cti_op_sub);
415     else {
416         ASSERT(opcodeID == op_mul);
417         emitCTICall(Interpreter::cti_op_mul);
418     }
419     Jump end = jump();
420 
421     // if we get here, eax is not an int32, edx not yet checked.
422     notImm1.link(this);
423     if (!types.first().definitelyIsNumber())
424         emitJumpIfNotImmediateNumber(X86::eax).linkTo(stubFunctionCall, this);
425     if (!types.second().definitelyIsNumber())
426         emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this);
427     addPtr(tagTypeNumberRegister, X86::eax);
428     m_assembler.movq_rr(X86::eax, X86::xmm1);
429     Jump op2isDouble = emitJumpIfNotImmediateInteger(X86::edx);
430     m_assembler.cvtsi2sd_rr(X86::edx, X86::xmm2);
431     Jump op2wasInteger = jump();
432 
433     // if we get here, eax IS an int32, edx is not.
434     notImm2.link(this);
435     if (!types.second().definitelyIsNumber())
436         emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this);
437     m_assembler.cvtsi2sd_rr(X86::eax, X86::xmm1);
438     op2isDouble.link(this);
439     addPtr(tagTypeNumberRegister, X86::edx);
440     m_assembler.movq_rr(X86::edx, X86::xmm2);
441     op2wasInteger.link(this);
442 
443     if (opcodeID == op_add)
444         m_assembler.addsd_rr(X86::xmm2, X86::xmm1);
445     else if (opcodeID == op_sub)
446         m_assembler.subsd_rr(X86::xmm2, X86::xmm1);
447     else {
448         ASSERT(opcodeID == op_mul);
449         m_assembler.mulsd_rr(X86::xmm2, X86::xmm1);
450     }
451     m_assembler.movq_rr(X86::xmm1, X86::eax);
452     subPtr(tagTypeNumberRegister, X86::eax);
453 
454     end.link(this);
455 }
456 
compileFastArith_op_add(Instruction * currentInstruction)457 void JIT::compileFastArith_op_add(Instruction* currentInstruction)
458 {
459     unsigned result = currentInstruction[1].u.operand;
460     unsigned op1 = currentInstruction[2].u.operand;
461     unsigned op2 = currentInstruction[3].u.operand;
462     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
463 
464     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
465         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
466         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
467         emitCTICall(Interpreter::cti_op_add);
468         emitPutVirtualRegister(result);
469         return;
470     }
471 
472     if (isOperandConstantImmediateInt(op1)) {
473         emitGetVirtualRegister(op2, X86::eax);
474         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
475         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax));
476         emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
477     } else if (isOperandConstantImmediateInt(op2)) {
478         emitGetVirtualRegister(op1, X86::eax);
479         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
480         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax));
481         emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
482     } else
483         compileBinaryArithOp(op_add, result, op1, op2, types);
484 
485     emitPutVirtualRegister(result);
486 }
compileFastArithSlow_op_add(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)487 void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
488 {
489     unsigned result = currentInstruction[1].u.operand;
490     unsigned op1 = currentInstruction[2].u.operand;
491     unsigned op2 = currentInstruction[3].u.operand;
492     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
493 
494     if (isOperandConstantImmediateInt(op1)) {
495         linkSlowCase(iter);
496         linkSlowCase(iter);
497         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
498         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
499         emitCTICall(Interpreter::cti_op_add);
500     } else if (isOperandConstantImmediateInt(op2)) {
501         linkSlowCase(iter);
502         linkSlowCase(iter);
503         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
504         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
505         emitCTICall(Interpreter::cti_op_add);
506     } else
507         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
508 
509     emitPutVirtualRegister(result);
510 }
511 
compileFastArith_op_mul(Instruction * currentInstruction)512 void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
513 {
514     unsigned result = currentInstruction[1].u.operand;
515     unsigned op1 = currentInstruction[2].u.operand;
516     unsigned op2 = currentInstruction[3].u.operand;
517     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
518 
519     // For now, only plant a fast int case if the constant operand is greater than zero.
520     int32_t value;
521     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
522         emitGetVirtualRegister(op2, X86::eax);
523         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
524         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
525         emitFastArithReTagImmediate(X86::eax, X86::eax);
526     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
527         emitGetVirtualRegister(op1, X86::eax);
528         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
529         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
530         emitFastArithReTagImmediate(X86::eax, X86::eax);
531     } else
532         compileBinaryArithOp(op_mul, result, op1, op2, types);
533 
534     emitPutVirtualRegister(result);
535 }
compileFastArithSlow_op_mul(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)536 void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
537 {
538     unsigned result = currentInstruction[1].u.operand;
539     unsigned op1 = currentInstruction[2].u.operand;
540     unsigned op2 = currentInstruction[3].u.operand;
541     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
542 
543     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
544         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
545         linkSlowCase(iter);
546         linkSlowCase(iter);
547         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
548         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
549         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
550         emitCTICall(Interpreter::cti_op_mul);
551     } else
552         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types);
553 
554     emitPutVirtualRegister(result);
555 }
556 
compileFastArith_op_sub(Instruction * currentInstruction)557 void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
558 {
559     unsigned result = currentInstruction[1].u.operand;
560     unsigned op1 = currentInstruction[2].u.operand;
561     unsigned op2 = currentInstruction[3].u.operand;
562     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
563 
564     compileBinaryArithOp(op_sub, result, op1, op2, types);
565 
566     emitPutVirtualRegister(result);
567 }
compileFastArithSlow_op_sub(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)568 void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
569 {
570     unsigned result = currentInstruction[1].u.operand;
571     unsigned op1 = currentInstruction[2].u.operand;
572     unsigned op2 = currentInstruction[3].u.operand;
573     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
574 
575     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types);
576 
577     emitPutVirtualRegister(result);
578 }
579 
580 #else
581 
582 typedef X86Assembler::JmpSrc JmpSrc;
583 typedef X86Assembler::JmpDst JmpDst;
584 typedef X86Assembler::XMMRegisterID XMMRegisterID;
585 
586 #if PLATFORM(MAC)
587 
isSSE2Present()588 static inline bool isSSE2Present()
589 {
590     return true; // All X86 Macs are guaranteed to support at least SSE2
591 }
592 
593 #else
594 
isSSE2Present()595 static bool isSSE2Present()
596 {
597     static const int SSE2FeatureBit = 1 << 26;
598     struct SSE2Check {
599         SSE2Check()
600         {
601             int flags;
602 #if COMPILER(MSVC)
603             _asm {
604                 mov eax, 1 // cpuid function 1 gives us the standard feature set
605                 cpuid;
606                 mov flags, edx;
607             }
608 #else
609             flags = 0;
610             // FIXME: Add GCC code to do above asm
611 #endif
612             present = (flags & SSE2FeatureBit) != 0;
613         }
614         bool present;
615     };
616     static SSE2Check check;
617     return check.present;
618 }
619 
620 #endif
621 
622 /*
623   This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell.
624 
625   In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell'
626   is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell).
627 
628   However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow
629   control will fall through from the code planted.
630 */
putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource,X86::RegisterID jsNumberCell,unsigned dst,JmpSrc * wroteJSNumberCell,X86::XMMRegisterID tempXmm,X86::RegisterID tempReg1,X86::RegisterID tempReg2)631 void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, JmpSrc* wroteJSNumberCell,  X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2)
632 {
633     // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate.
634     __ cvttsd2si_rr(xmmSource, tempReg1);
635     __ addl_rr(tempReg1, tempReg1);
636     __ sarl_i8r(1, tempReg1);
637     __ cvtsi2sd_rr(tempReg1, tempXmm);
638     // Compare & branch if immediate.
639     __ ucomisd_rr(tempXmm, xmmSource);
640     JmpSrc resultIsImm = __ je();
641     JmpDst resultLookedLikeImmButActuallyIsnt = __ label();
642 
643     // Store the result to the JSNumberCell and jump.
644     __ movsd_rm(xmmSource, FIELD_OFFSET(JSNumberCell, m_value), jsNumberCell);
645     if (jsNumberCell != X86::eax)
646         __ movl_rr(jsNumberCell, X86::eax);
647     emitPutVirtualRegister(dst);
648     *wroteJSNumberCell = __ jmp();
649 
650     __ link(resultIsImm, __ label());
651     // value == (double)(JSImmediate)value... or at least, it looks that way...
652     // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered).
653     __ link(__ jp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN
654     __ pextrw_irr(3, xmmSource, tempReg2);
655     __ cmpl_ir(0x8000, tempReg2);
656     __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
657     // Yes it really really really is representable as a JSImmediate.
658     emitFastArithIntToImmNoCheck(tempReg1, X86::eax);
659     emitPutVirtualRegister(dst);
660 }
661 
compileBinaryArithOp(OpcodeID opcodeID,unsigned dst,unsigned src1,unsigned src2,OperandTypes types)662 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
663 {
664     Structure* numberStructure = m_globalData->numberStructure.get();
665     JmpSrc wasJSNumberCell1;
666     JmpSrc wasJSNumberCell1b;
667     JmpSrc wasJSNumberCell2;
668     JmpSrc wasJSNumberCell2b;
669 
670     emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
671 
672     if (types.second().isReusable() && isSSE2Present()) {
673         ASSERT(types.second().mightBeNumber());
674 
675         // Check op2 is a number
676         __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);
677         JmpSrc op2imm = __ jne();
678         if (!types.second().definitelyIsNumber()) {
679             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
680             __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
681             addSlowCase(__ jne());
682         }
683 
684         // (1) In this case src2 is a reusable number cell.
685         //     Slow case if src1 is not a number type.
686         __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);
687         JmpSrc op1imm = __ jne();
688         if (!types.first().definitelyIsNumber()) {
689             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
690             __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
691             addSlowCase(__ jne());
692         }
693 
694         // (1a) if we get here, src1 is also a number cell
695         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
696         JmpSrc loadedDouble = __ jmp();
697         // (1b) if we get here, src1 is an immediate
698         __ link(op1imm, __ label());
699         emitFastArithImmToInt(X86::eax);
700         __ cvtsi2sd_rr(X86::eax, X86::xmm0);
701         // (1c)
702         __ link(loadedDouble, __ label());
703         if (opcodeID == op_add)
704             __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
705         else if (opcodeID == op_sub)
706             __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
707         else {
708             ASSERT(opcodeID == op_mul);
709             __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
710         }
711 
712         putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax);
713         wasJSNumberCell2b = __ jmp();
714 
715         // (2) This handles cases where src2 is an immediate number.
716         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
717         __ link(op2imm, __ label());
718         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
719     } else if (types.first().isReusable() && isSSE2Present()) {
720         ASSERT(types.first().mightBeNumber());
721 
722         // Check op1 is a number
723         __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);
724         JmpSrc op1imm = __ jne();
725         if (!types.first().definitelyIsNumber()) {
726             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
727             __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
728             addSlowCase(__ jne());
729         }
730 
731         // (1) In this case src1 is a reusable number cell.
732         //     Slow case if src2 is not a number type.
733         __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);
734         JmpSrc op2imm = __ jne();
735         if (!types.second().definitelyIsNumber()) {
736             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
737             __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
738             addSlowCase(__ jne());
739         }
740 
741         // (1a) if we get here, src2 is also a number cell
742         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1);
743         JmpSrc loadedDouble = __ jmp();
744         // (1b) if we get here, src2 is an immediate
745         __ link(op2imm, __ label());
746         emitFastArithImmToInt(X86::edx);
747         __ cvtsi2sd_rr(X86::edx, X86::xmm1);
748         // (1c)
749         __ link(loadedDouble, __ label());
750         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
751         if (opcodeID == op_add)
752             __ addsd_rr(X86::xmm1, X86::xmm0);
753         else if (opcodeID == op_sub)
754             __ subsd_rr(X86::xmm1, X86::xmm0);
755         else {
756             ASSERT(opcodeID == op_mul);
757             __ mulsd_rr(X86::xmm1, X86::xmm0);
758         }
759         __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);
760         emitPutVirtualRegister(dst);
761 
762         putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx);
763         wasJSNumberCell1b = __ jmp();
764 
765         // (2) This handles cases where src1 is an immediate number.
766         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
767         __ link(op1imm, __ label());
768         emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
769     } else
770         emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
771 
772     if (opcodeID == op_add) {
773         emitFastArithDeTagImmediate(X86::eax);
774         __ addl_rr(X86::edx, X86::eax);
775         addSlowCase(__ jo());
776     } else  if (opcodeID == op_sub) {
777         __ subl_rr(X86::edx, X86::eax);
778         addSlowCase(__ jo());
779         signExtend32ToPtr(X86::eax, X86::eax);
780         emitFastArithReTagImmediate(X86::eax, X86::eax);
781     } else {
782         ASSERT(opcodeID == op_mul);
783         // convert eax & edx from JSImmediates to ints, and check if either are zero
784         emitFastArithImmToInt(X86::edx);
785         JmpSrc op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax);
786         __ testl_rr(X86::edx, X86::edx);
787         JmpSrc op2NonZero = __ jne();
788         __ link(op1Zero, __ label());
789         // if either input is zero, add the two together, and check if the result is < 0.
790         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
791         __ movl_rr(X86::eax, X86::ecx);
792         __ addl_rr(X86::edx, X86::ecx);
793         addSlowCase(__ js());
794         // Skip the above check if neither input is zero
795         __ link(op2NonZero, __ label());
796         __ imull_rr(X86::edx, X86::eax);
797         addSlowCase(__ jo());
798         signExtend32ToPtr(X86::eax, X86::eax);
799         emitFastArithReTagImmediate(X86::eax, X86::eax);
800     }
801     emitPutVirtualRegister(dst);
802 
803     if (types.second().isReusable() && isSSE2Present()) {
804         __ link(wasJSNumberCell2, __ label());
805         __ link(wasJSNumberCell2b, __ label());
806     }
807     else if (types.first().isReusable() && isSSE2Present()) {
808         __ link(wasJSNumberCell1, __ label());
809         __ link(wasJSNumberCell1b, __ label());
810     }
811 }
812 
compileBinaryArithOpSlowCase(OpcodeID opcodeID,Vector<SlowCaseEntry>::iterator & iter,unsigned dst,unsigned src1,unsigned src2,OperandTypes types)813 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
814 {
815     linkSlowCase(iter);
816     if (types.second().isReusable() && isSSE2Present()) {
817         if (!types.first().definitelyIsNumber()) {
818             linkSlowCaseIfNotJSCell(iter, src1);
819             linkSlowCase(iter);
820         }
821         if (!types.second().definitelyIsNumber()) {
822             linkSlowCaseIfNotJSCell(iter, src2);
823             linkSlowCase(iter);
824         }
825     } else if (types.first().isReusable() && isSSE2Present()) {
826         if (!types.first().definitelyIsNumber()) {
827             linkSlowCaseIfNotJSCell(iter, src1);
828             linkSlowCase(iter);
829         }
830         if (!types.second().definitelyIsNumber()) {
831             linkSlowCaseIfNotJSCell(iter, src2);
832             linkSlowCase(iter);
833         }
834     }
835     linkSlowCase(iter);
836 
837     // additional entry point to handle -0 cases.
838     if (opcodeID == op_mul)
839         linkSlowCase(iter);
840 
841     emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
842     emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
843     if (opcodeID == op_add)
844         emitCTICall(Interpreter::cti_op_add);
845     else if (opcodeID == op_sub)
846         emitCTICall(Interpreter::cti_op_sub);
847     else {
848         ASSERT(opcodeID == op_mul);
849         emitCTICall(Interpreter::cti_op_mul);
850     }
851     emitPutVirtualRegister(dst);
852 }
853 
compileFastArith_op_add(Instruction * currentInstruction)854 void JIT::compileFastArith_op_add(Instruction* currentInstruction)
855 {
856     unsigned result = currentInstruction[1].u.operand;
857     unsigned op1 = currentInstruction[2].u.operand;
858     unsigned op2 = currentInstruction[3].u.operand;
859 
860     if (isOperandConstantImmediateInt(op1)) {
861         emitGetVirtualRegister(op2, X86::eax);
862         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
863         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax));
864         signExtend32ToPtr(X86::eax, X86::eax);
865         emitPutVirtualRegister(result);
866     } else if (isOperandConstantImmediateInt(op2)) {
867         emitGetVirtualRegister(op1, X86::eax);
868         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
869         addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax));
870         signExtend32ToPtr(X86::eax, X86::eax);
871         emitPutVirtualRegister(result);
872     } else {
873         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
874         if (types.first().mightBeNumber() && types.second().mightBeNumber())
875             compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
876         else {
877             emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
878             emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
879             emitCTICall(Interpreter::cti_op_add);
880             emitPutVirtualRegister(result);
881         }
882     }
883 }
compileFastArithSlow_op_add(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)884 void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
885 {
886     unsigned result = currentInstruction[1].u.operand;
887     unsigned op1 = currentInstruction[2].u.operand;
888     unsigned op2 = currentInstruction[3].u.operand;
889 
890     if (isOperandConstantImmediateInt(op1)) {
891         Jump notImm = getSlowCase(iter);
892         linkSlowCase(iter);
893         sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax);
894         notImm.link(this);
895         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
896         emitPutJITStubArg(X86::eax, 2);
897         emitCTICall(Interpreter::cti_op_add);
898         emitPutVirtualRegister(result);
899     } else if (isOperandConstantImmediateInt(op2)) {
900         Jump notImm = getSlowCase(iter);
901         linkSlowCase(iter);
902         sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax);
903         notImm.link(this);
904         emitPutJITStubArg(X86::eax, 1);
905         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
906         emitCTICall(Interpreter::cti_op_add);
907         emitPutVirtualRegister(result);
908     } else {
909         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
910         ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
911         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
912     }
913 }
914 
compileFastArith_op_mul(Instruction * currentInstruction)915 void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
916 {
917     unsigned result = currentInstruction[1].u.operand;
918     unsigned op1 = currentInstruction[2].u.operand;
919     unsigned op2 = currentInstruction[3].u.operand;
920 
921     // For now, only plant a fast int case if the constant operand is greater than zero.
922     int32_t value;
923     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
924         emitGetVirtualRegister(op2, X86::eax);
925         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
926         emitFastArithDeTagImmediate(X86::eax);
927         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
928         signExtend32ToPtr(X86::eax, X86::eax);
929         emitFastArithReTagImmediate(X86::eax, X86::eax);
930         emitPutVirtualRegister(result);
931     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
932         emitGetVirtualRegister(op1, X86::eax);
933         emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
934         emitFastArithDeTagImmediate(X86::eax);
935         addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
936         signExtend32ToPtr(X86::eax, X86::eax);
937         emitFastArithReTagImmediate(X86::eax, X86::eax);
938         emitPutVirtualRegister(result);
939     } else
940         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
941 }
compileFastArithSlow_op_mul(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)942 void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
943 {
944     unsigned result = currentInstruction[1].u.operand;
945     unsigned op1 = currentInstruction[2].u.operand;
946     unsigned op2 = currentInstruction[3].u.operand;
947 
948     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
949         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
950         linkSlowCase(iter);
951         linkSlowCase(iter);
952         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
953         emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
954         emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
955         emitCTICall(Interpreter::cti_op_mul);
956         emitPutVirtualRegister(result);
957     } else
958         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
959 }
960 
compileFastArith_op_sub(Instruction * currentInstruction)961 void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
962 {
963     compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
964 }
compileFastArithSlow_op_sub(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)965 void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
966 {
967     compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
968 }
969 
970 #endif
971 
972 } // namespace JSC
973 
974 #endif // ENABLE(JIT)
975