• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(JIT)
29 #if USE(JSVALUE64)
30 #include "JIT.h"
31 
32 #include "CodeBlock.h"
33 #include "JITInlineMethods.h"
34 #include "JITStubCall.h"
35 #include "JITStubs.h"
36 #include "JSArray.h"
37 #include "JSFunction.h"
38 #include "Interpreter.h"
39 #include "ResultType.h"
40 #include "SamplingTool.h"
41 
42 #ifndef NDEBUG
43 #include <stdio.h>
44 #endif
45 
46 using namespace std;
47 
48 namespace JSC {
49 
emit_op_lshift(Instruction * currentInstruction)50 void JIT::emit_op_lshift(Instruction* currentInstruction)
51 {
52     unsigned result = currentInstruction[1].u.operand;
53     unsigned op1 = currentInstruction[2].u.operand;
54     unsigned op2 = currentInstruction[3].u.operand;
55 
56     emitGetVirtualRegisters(op1, regT0, op2, regT2);
57     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
58     emitJumpSlowCaseIfNotImmediateInteger(regT0);
59     emitJumpSlowCaseIfNotImmediateInteger(regT2);
60     emitFastArithImmToInt(regT0);
61     emitFastArithImmToInt(regT2);
62     lshift32(regT2, regT0);
63     emitFastArithReTagImmediate(regT0, regT0);
64     emitPutVirtualRegister(result);
65 }
66 
emitSlow_op_lshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)67 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
68 {
69     unsigned result = currentInstruction[1].u.operand;
70     unsigned op1 = currentInstruction[2].u.operand;
71     unsigned op2 = currentInstruction[3].u.operand;
72 
73     UNUSED_PARAM(op1);
74     UNUSED_PARAM(op2);
75     linkSlowCase(iter);
76     linkSlowCase(iter);
77     JITStubCall stubCall(this, cti_op_lshift);
78     stubCall.addArgument(regT0);
79     stubCall.addArgument(regT2);
80     stubCall.call(result);
81 }
82 
emit_op_rshift(Instruction * currentInstruction)83 void JIT::emit_op_rshift(Instruction* currentInstruction)
84 {
85     unsigned result = currentInstruction[1].u.operand;
86     unsigned op1 = currentInstruction[2].u.operand;
87     unsigned op2 = currentInstruction[3].u.operand;
88 
89     if (isOperandConstantImmediateInt(op2)) {
90         // isOperandConstantImmediateInt(op2) => 1 SlowCase
91         emitGetVirtualRegister(op1, regT0);
92         emitJumpSlowCaseIfNotImmediateInteger(regT0);
93         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
94         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
95     } else {
96         emitGetVirtualRegisters(op1, regT0, op2, regT2);
97         if (supportsFloatingPointTruncate()) {
98             Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
99             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
100             addSlowCase(emitJumpIfNotImmediateNumber(regT0));
101             addPtr(tagTypeNumberRegister, regT0);
102             movePtrToDouble(regT0, fpRegT0);
103             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
104             lhsIsInt.link(this);
105             emitJumpSlowCaseIfNotImmediateInteger(regT2);
106         } else {
107             // !supportsFloatingPoint() => 2 SlowCases
108             emitJumpSlowCaseIfNotImmediateInteger(regT0);
109             emitJumpSlowCaseIfNotImmediateInteger(regT2);
110         }
111         emitFastArithImmToInt(regT2);
112         rshift32(regT2, regT0);
113     }
114     emitFastArithIntToImmNoCheck(regT0, regT0);
115     emitPutVirtualRegister(result);
116 }
117 
emitSlow_op_rshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)118 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
119 {
120     unsigned result = currentInstruction[1].u.operand;
121     unsigned op1 = currentInstruction[2].u.operand;
122     unsigned op2 = currentInstruction[3].u.operand;
123 
124     JITStubCall stubCall(this, cti_op_rshift);
125 
126     if (isOperandConstantImmediateInt(op2)) {
127         linkSlowCase(iter);
128         stubCall.addArgument(regT0);
129         stubCall.addArgument(op2, regT2);
130     } else {
131         if (supportsFloatingPointTruncate()) {
132             linkSlowCase(iter);
133             linkSlowCase(iter);
134             linkSlowCase(iter);
135             // We're reloading op1 to regT0 as we can no longer guarantee that
136             // we have not munged the operand.  It may have already been shifted
137             // correctly, but it still will not have been tagged.
138             stubCall.addArgument(op1, regT0);
139             stubCall.addArgument(regT2);
140         } else {
141             linkSlowCase(iter);
142             linkSlowCase(iter);
143             stubCall.addArgument(regT0);
144             stubCall.addArgument(regT2);
145         }
146     }
147 
148     stubCall.call(result);
149 }
150 
emit_op_urshift(Instruction * currentInstruction)151 void JIT::emit_op_urshift(Instruction* currentInstruction)
152 {
153     unsigned dst = currentInstruction[1].u.operand;
154     unsigned op1 = currentInstruction[2].u.operand;
155     unsigned op2 = currentInstruction[3].u.operand;
156 
157     // Slow case of urshift makes assumptions about what registers hold the
158     // shift arguments, so any changes must be updated there as well.
159     if (isOperandConstantImmediateInt(op2)) {
160         emitGetVirtualRegister(op1, regT0);
161         emitJumpSlowCaseIfNotImmediateInteger(regT0);
162         emitFastArithImmToInt(regT0);
163         int shift = getConstantOperand(op2).asInt32();
164         if (shift)
165             urshift32(Imm32(shift & 0x1f), regT0);
166         // unsigned shift < 0 or shift = k*2^32 may result in (essentially)
167         // a toUint conversion, which can result in a value we can represent
168         // as an immediate int.
169         if (shift < 0 || !(shift & 31))
170             addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
171         emitFastArithReTagImmediate(regT0, regT0);
172         emitPutVirtualRegister(dst, regT0);
173         return;
174     }
175     emitGetVirtualRegisters(op1, regT0, op2, regT1);
176     if (!isOperandConstantImmediateInt(op1))
177         emitJumpSlowCaseIfNotImmediateInteger(regT0);
178     emitJumpSlowCaseIfNotImmediateInteger(regT1);
179     emitFastArithImmToInt(regT0);
180     emitFastArithImmToInt(regT1);
181     urshift32(regT1, regT0);
182     addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
183     emitFastArithReTagImmediate(regT0, regT0);
184     emitPutVirtualRegister(dst, regT0);
185 }
186 
emitSlow_op_urshift(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)187 void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
188 {
189     unsigned dst = currentInstruction[1].u.operand;
190     unsigned op1 = currentInstruction[2].u.operand;
191     unsigned op2 = currentInstruction[3].u.operand;
192     if (isOperandConstantImmediateInt(op2)) {
193         int shift = getConstantOperand(op2).asInt32();
194         // op1 = regT0
195         linkSlowCase(iter); // int32 check
196         if (supportsFloatingPointTruncate()) {
197             JumpList failures;
198             failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
199             addPtr(tagTypeNumberRegister, regT0);
200             movePtrToDouble(regT0, fpRegT0);
201             failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
202             if (shift)
203                 urshift32(Imm32(shift & 0x1f), regT0);
204             if (shift < 0 || !(shift & 31))
205                 failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
206             emitFastArithReTagImmediate(regT0, regT0);
207             emitPutVirtualRegister(dst, regT0);
208             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
209             failures.link(this);
210         }
211         if (shift < 0 || !(shift & 31))
212             linkSlowCase(iter); // failed to box in hot path
213     } else {
214         // op1 = regT0
215         // op2 = regT1
216         if (!isOperandConstantImmediateInt(op1)) {
217             linkSlowCase(iter); // int32 check -- op1 is not an int
218             if (supportsFloatingPointTruncate()) {
219                 JumpList failures;
220                 failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
221                 addPtr(tagTypeNumberRegister, regT0);
222                 movePtrToDouble(regT0, fpRegT0);
223                 failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
224                 failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int
225                 emitFastArithImmToInt(regT1);
226                 urshift32(regT1, regT0);
227                 failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
228                 emitFastArithReTagImmediate(regT0, regT0);
229                 emitPutVirtualRegister(dst, regT0);
230                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
231                 failures.link(this);
232             }
233         }
234 
235         linkSlowCase(iter); // int32 check - op2 is not an int
236         linkSlowCase(iter); // Can't represent unsigned result as an immediate
237     }
238 
239     JITStubCall stubCall(this, cti_op_urshift);
240     stubCall.addArgument(op1, regT0);
241     stubCall.addArgument(op2, regT1);
242     stubCall.call(dst);
243 }
244 
emit_op_jnless(Instruction * currentInstruction)245 void JIT::emit_op_jnless(Instruction* currentInstruction)
246 {
247     unsigned op1 = currentInstruction[1].u.operand;
248     unsigned op2 = currentInstruction[2].u.operand;
249     unsigned target = currentInstruction[3].u.operand;
250 
251     // We generate inline code for the following cases in the fast path:
252     // - int immediate to constant int immediate
253     // - constant int immediate to int immediate
254     // - int immediate to int immediate
255 
256     if (isOperandConstantImmediateChar(op1)) {
257         emitGetVirtualRegister(op2, regT0);
258         addSlowCase(emitJumpIfNotJSCell(regT0));
259         JumpList failures;
260         emitLoadCharacterString(regT0, regT0, failures);
261         addSlowCase(failures);
262         addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
263         return;
264     }
265     if (isOperandConstantImmediateChar(op2)) {
266         emitGetVirtualRegister(op1, regT0);
267         addSlowCase(emitJumpIfNotJSCell(regT0));
268         JumpList failures;
269         emitLoadCharacterString(regT0, regT0, failures);
270         addSlowCase(failures);
271         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
272         return;
273     }
274     if (isOperandConstantImmediateInt(op2)) {
275         emitGetVirtualRegister(op1, regT0);
276         emitJumpSlowCaseIfNotImmediateInteger(regT0);
277         int32_t op2imm = getConstantOperandImmediateInt(op2);
278         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
279     } else if (isOperandConstantImmediateInt(op1)) {
280         emitGetVirtualRegister(op2, regT1);
281         emitJumpSlowCaseIfNotImmediateInteger(regT1);
282         int32_t op1imm = getConstantOperandImmediateInt(op1);
283         addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
284     } else {
285         emitGetVirtualRegisters(op1, regT0, op2, regT1);
286         emitJumpSlowCaseIfNotImmediateInteger(regT0);
287         emitJumpSlowCaseIfNotImmediateInteger(regT1);
288 
289         addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
290     }
291 }
292 
emitSlow_op_jnless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)293 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
294 {
295     unsigned op1 = currentInstruction[1].u.operand;
296     unsigned op2 = currentInstruction[2].u.operand;
297     unsigned target = currentInstruction[3].u.operand;
298 
299     // We generate inline code for the following cases in the slow path:
300     // - floating-point number to constant int immediate
301     // - constant int immediate to floating-point number
302     // - floating-point number to floating-point number.
303     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
304         linkSlowCase(iter);
305         linkSlowCase(iter);
306         linkSlowCase(iter);
307         linkSlowCase(iter);
308         JITStubCall stubCall(this, cti_op_jless);
309         stubCall.addArgument(op1, regT0);
310         stubCall.addArgument(op2, regT1);
311         stubCall.call();
312         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
313         return;
314     }
315 
316     if (isOperandConstantImmediateInt(op2)) {
317         linkSlowCase(iter);
318 
319         if (supportsFloatingPoint()) {
320             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
321             addPtr(tagTypeNumberRegister, regT0);
322             movePtrToDouble(regT0, fpRegT0);
323 
324             int32_t op2imm = getConstantOperand(op2).asInt32();;
325 
326             move(Imm32(op2imm), regT1);
327             convertInt32ToDouble(regT1, fpRegT1);
328 
329             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
330 
331             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
332 
333             fail1.link(this);
334         }
335 
336         JITStubCall stubCall(this, cti_op_jless);
337         stubCall.addArgument(regT0);
338         stubCall.addArgument(op2, regT2);
339         stubCall.call();
340         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
341 
342     } else if (isOperandConstantImmediateInt(op1)) {
343         linkSlowCase(iter);
344 
345         if (supportsFloatingPoint()) {
346             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
347             addPtr(tagTypeNumberRegister, regT1);
348             movePtrToDouble(regT1, fpRegT1);
349 
350             int32_t op1imm = getConstantOperand(op1).asInt32();;
351 
352             move(Imm32(op1imm), regT0);
353             convertInt32ToDouble(regT0, fpRegT0);
354 
355             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
356 
357             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
358 
359             fail1.link(this);
360         }
361 
362         JITStubCall stubCall(this, cti_op_jless);
363         stubCall.addArgument(op1, regT2);
364         stubCall.addArgument(regT1);
365         stubCall.call();
366         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
367 
368     } else {
369         linkSlowCase(iter);
370 
371         if (supportsFloatingPoint()) {
372             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
373             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
374             Jump fail3 = emitJumpIfImmediateInteger(regT1);
375             addPtr(tagTypeNumberRegister, regT0);
376             addPtr(tagTypeNumberRegister, regT1);
377             movePtrToDouble(regT0, fpRegT0);
378             movePtrToDouble(regT1, fpRegT1);
379 
380             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
381 
382             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
383 
384             fail1.link(this);
385             fail2.link(this);
386             fail3.link(this);
387         }
388 
389         linkSlowCase(iter);
390         JITStubCall stubCall(this, cti_op_jless);
391         stubCall.addArgument(regT0);
392         stubCall.addArgument(regT1);
393         stubCall.call();
394         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
395     }
396 }
397 
emit_op_jless(Instruction * currentInstruction)398 void JIT::emit_op_jless(Instruction* currentInstruction)
399 {
400     unsigned op1 = currentInstruction[1].u.operand;
401     unsigned op2 = currentInstruction[2].u.operand;
402     unsigned target = currentInstruction[3].u.operand;
403 
404     // We generate inline code for the following cases in the fast path:
405     // - int immediate to constant int immediate
406     // - constant int immediate to int immediate
407     // - int immediate to int immediate
408 
409     if (isOperandConstantImmediateChar(op1)) {
410         emitGetVirtualRegister(op2, regT0);
411         addSlowCase(emitJumpIfNotJSCell(regT0));
412         JumpList failures;
413         emitLoadCharacterString(regT0, regT0, failures);
414         addSlowCase(failures);
415         addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
416         return;
417     }
418     if (isOperandConstantImmediateChar(op2)) {
419         emitGetVirtualRegister(op1, regT0);
420         addSlowCase(emitJumpIfNotJSCell(regT0));
421         JumpList failures;
422         emitLoadCharacterString(regT0, regT0, failures);
423         addSlowCase(failures);
424         addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
425         return;
426     }
427     if (isOperandConstantImmediateInt(op2)) {
428         emitGetVirtualRegister(op1, regT0);
429         emitJumpSlowCaseIfNotImmediateInteger(regT0);
430         int32_t op2imm = getConstantOperandImmediateInt(op2);
431         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
432     } else if (isOperandConstantImmediateInt(op1)) {
433         emitGetVirtualRegister(op2, regT1);
434         emitJumpSlowCaseIfNotImmediateInteger(regT1);
435         int32_t op1imm = getConstantOperandImmediateInt(op1);
436         addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
437     } else {
438         emitGetVirtualRegisters(op1, regT0, op2, regT1);
439         emitJumpSlowCaseIfNotImmediateInteger(regT0);
440         emitJumpSlowCaseIfNotImmediateInteger(regT1);
441 
442         addJump(branch32(LessThan, regT0, regT1), target);
443     }
444 }
445 
emitSlow_op_jless(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)446 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
447 {
448     unsigned op1 = currentInstruction[1].u.operand;
449     unsigned op2 = currentInstruction[2].u.operand;
450     unsigned target = currentInstruction[3].u.operand;
451 
452     // We generate inline code for the following cases in the slow path:
453     // - floating-point number to constant int immediate
454     // - constant int immediate to floating-point number
455     // - floating-point number to floating-point number.
456     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
457         linkSlowCase(iter);
458         linkSlowCase(iter);
459         linkSlowCase(iter);
460         linkSlowCase(iter);
461         JITStubCall stubCall(this, cti_op_jless);
462         stubCall.addArgument(op1, regT0);
463         stubCall.addArgument(op2, regT1);
464         stubCall.call();
465         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
466         return;
467     }
468 
469     if (isOperandConstantImmediateInt(op2)) {
470         linkSlowCase(iter);
471 
472         if (supportsFloatingPoint()) {
473             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
474             addPtr(tagTypeNumberRegister, regT0);
475             movePtrToDouble(regT0, fpRegT0);
476 
477             int32_t op2imm = getConstantOperand(op2).asInt32();
478 
479             move(Imm32(op2imm), regT1);
480             convertInt32ToDouble(regT1, fpRegT1);
481 
482             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
483 
484             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
485 
486             fail1.link(this);
487         }
488 
489         JITStubCall stubCall(this, cti_op_jless);
490         stubCall.addArgument(regT0);
491         stubCall.addArgument(op2, regT2);
492         stubCall.call();
493         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
494 
495     } else if (isOperandConstantImmediateInt(op1)) {
496         linkSlowCase(iter);
497 
498         if (supportsFloatingPoint()) {
499             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
500             addPtr(tagTypeNumberRegister, regT1);
501             movePtrToDouble(regT1, fpRegT1);
502 
503             int32_t op1imm = getConstantOperand(op1).asInt32();
504 
505             move(Imm32(op1imm), regT0);
506             convertInt32ToDouble(regT0, fpRegT0);
507 
508             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
509 
510             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
511 
512             fail1.link(this);
513         }
514 
515         JITStubCall stubCall(this, cti_op_jless);
516         stubCall.addArgument(op1, regT2);
517         stubCall.addArgument(regT1);
518         stubCall.call();
519         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
520 
521     } else {
522         linkSlowCase(iter);
523 
524         if (supportsFloatingPoint()) {
525             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
526             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
527             Jump fail3 = emitJumpIfImmediateInteger(regT1);
528             addPtr(tagTypeNumberRegister, regT0);
529             addPtr(tagTypeNumberRegister, regT1);
530             movePtrToDouble(regT0, fpRegT0);
531             movePtrToDouble(regT1, fpRegT1);
532 
533             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
534 
535             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
536 
537             fail1.link(this);
538             fail2.link(this);
539             fail3.link(this);
540         }
541 
542         linkSlowCase(iter);
543         JITStubCall stubCall(this, cti_op_jless);
544         stubCall.addArgument(regT0);
545         stubCall.addArgument(regT1);
546         stubCall.call();
547         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
548     }
549 }
550 
emit_op_jlesseq(Instruction * currentInstruction,bool invert)551 void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
552 {
553     unsigned op1 = currentInstruction[1].u.operand;
554     unsigned op2 = currentInstruction[2].u.operand;
555     unsigned target = currentInstruction[3].u.operand;
556 
557     // We generate inline code for the following cases in the fast path:
558     // - int immediate to constant int immediate
559     // - constant int immediate to int immediate
560     // - int immediate to int immediate
561 
562     if (isOperandConstantImmediateChar(op1)) {
563         emitGetVirtualRegister(op2, regT0);
564         addSlowCase(emitJumpIfNotJSCell(regT0));
565         JumpList failures;
566         emitLoadCharacterString(regT0, regT0, failures);
567         addSlowCase(failures);
568         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
569         return;
570     }
571     if (isOperandConstantImmediateChar(op2)) {
572         emitGetVirtualRegister(op1, regT0);
573         addSlowCase(emitJumpIfNotJSCell(regT0));
574         JumpList failures;
575         emitLoadCharacterString(regT0, regT0, failures);
576         addSlowCase(failures);
577         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
578         return;
579     }
580     if (isOperandConstantImmediateInt(op2)) {
581         emitGetVirtualRegister(op1, regT0);
582         emitJumpSlowCaseIfNotImmediateInteger(regT0);
583         int32_t op2imm = getConstantOperandImmediateInt(op2);
584         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target);
585     } else if (isOperandConstantImmediateInt(op1)) {
586         emitGetVirtualRegister(op2, regT1);
587         emitJumpSlowCaseIfNotImmediateInteger(regT1);
588         int32_t op1imm = getConstantOperandImmediateInt(op1);
589         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target);
590     } else {
591         emitGetVirtualRegisters(op1, regT0, op2, regT1);
592         emitJumpSlowCaseIfNotImmediateInteger(regT0);
593         emitJumpSlowCaseIfNotImmediateInteger(regT1);
594 
595         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT1), target);
596     }
597 }
598 
emitSlow_op_jlesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter,bool invert)599 void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert)
600 {
601     unsigned op1 = currentInstruction[1].u.operand;
602     unsigned op2 = currentInstruction[2].u.operand;
603     unsigned target = currentInstruction[3].u.operand;
604 
605     // We generate inline code for the following cases in the slow path:
606     // - floating-point number to constant int immediate
607     // - constant int immediate to floating-point number
608     // - floating-point number to floating-point number.
609 
610     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
611         linkSlowCase(iter);
612         linkSlowCase(iter);
613         linkSlowCase(iter);
614         linkSlowCase(iter);
615         JITStubCall stubCall(this, cti_op_jlesseq);
616         stubCall.addArgument(op1, regT0);
617         stubCall.addArgument(op2, regT1);
618         stubCall.call();
619         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
620         return;
621     }
622 
623     if (isOperandConstantImmediateInt(op2)) {
624         linkSlowCase(iter);
625 
626         if (supportsFloatingPoint()) {
627             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
628             addPtr(tagTypeNumberRegister, regT0);
629             movePtrToDouble(regT0, fpRegT0);
630 
631             int32_t op2imm = getConstantOperand(op2).asInt32();;
632 
633             move(Imm32(op2imm), regT1);
634             convertInt32ToDouble(regT1, fpRegT1);
635 
636             emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
637 
638             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
639 
640             fail1.link(this);
641         }
642 
643         JITStubCall stubCall(this, cti_op_jlesseq);
644         stubCall.addArgument(regT0);
645         stubCall.addArgument(op2, regT2);
646         stubCall.call();
647         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
648 
649     } else if (isOperandConstantImmediateInt(op1)) {
650         linkSlowCase(iter);
651 
652         if (supportsFloatingPoint()) {
653             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
654             addPtr(tagTypeNumberRegister, regT1);
655             movePtrToDouble(regT1, fpRegT1);
656 
657             int32_t op1imm = getConstantOperand(op1).asInt32();;
658 
659             move(Imm32(op1imm), regT0);
660             convertInt32ToDouble(regT0, fpRegT0);
661 
662             emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
663 
664             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
665 
666             fail1.link(this);
667         }
668 
669         JITStubCall stubCall(this, cti_op_jlesseq);
670         stubCall.addArgument(op1, regT2);
671         stubCall.addArgument(regT1);
672         stubCall.call();
673         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
674 
675     } else {
676         linkSlowCase(iter);
677 
678         if (supportsFloatingPoint()) {
679             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
680             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
681             Jump fail3 = emitJumpIfImmediateInteger(regT1);
682             addPtr(tagTypeNumberRegister, regT0);
683             addPtr(tagTypeNumberRegister, regT1);
684             movePtrToDouble(regT0, fpRegT0);
685             movePtrToDouble(regT1, fpRegT1);
686 
687             emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
688 
689             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
690 
691             fail1.link(this);
692             fail2.link(this);
693             fail3.link(this);
694         }
695 
696         linkSlowCase(iter);
697         JITStubCall stubCall(this, cti_op_jlesseq);
698         stubCall.addArgument(regT0);
699         stubCall.addArgument(regT1);
700         stubCall.call();
701         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
702     }
703 }
704 
emit_op_jnlesseq(Instruction * currentInstruction)705 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
706 {
707     emit_op_jlesseq(currentInstruction, true);
708 }
709 
emitSlow_op_jnlesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)710 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
711 {
712     emitSlow_op_jlesseq(currentInstruction, iter, true);
713 }
714 
emit_op_bitand(Instruction * currentInstruction)715 void JIT::emit_op_bitand(Instruction* currentInstruction)
716 {
717     unsigned result = currentInstruction[1].u.operand;
718     unsigned op1 = currentInstruction[2].u.operand;
719     unsigned op2 = currentInstruction[3].u.operand;
720 
721     if (isOperandConstantImmediateInt(op1)) {
722         emitGetVirtualRegister(op2, regT0);
723         emitJumpSlowCaseIfNotImmediateInteger(regT0);
724         int32_t imm = getConstantOperandImmediateInt(op1);
725         andPtr(Imm32(imm), regT0);
726         if (imm >= 0)
727             emitFastArithIntToImmNoCheck(regT0, regT0);
728     } else if (isOperandConstantImmediateInt(op2)) {
729         emitGetVirtualRegister(op1, regT0);
730         emitJumpSlowCaseIfNotImmediateInteger(regT0);
731         int32_t imm = getConstantOperandImmediateInt(op2);
732         andPtr(Imm32(imm), regT0);
733         if (imm >= 0)
734             emitFastArithIntToImmNoCheck(regT0, regT0);
735     } else {
736         emitGetVirtualRegisters(op1, regT0, op2, regT1);
737         andPtr(regT1, regT0);
738         emitJumpSlowCaseIfNotImmediateInteger(regT0);
739     }
740     emitPutVirtualRegister(result);
741 }
742 
emitSlow_op_bitand(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)743 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
744 {
745     unsigned result = currentInstruction[1].u.operand;
746     unsigned op1 = currentInstruction[2].u.operand;
747     unsigned op2 = currentInstruction[3].u.operand;
748 
749     linkSlowCase(iter);
750     if (isOperandConstantImmediateInt(op1)) {
751         JITStubCall stubCall(this, cti_op_bitand);
752         stubCall.addArgument(op1, regT2);
753         stubCall.addArgument(regT0);
754         stubCall.call(result);
755     } else if (isOperandConstantImmediateInt(op2)) {
756         JITStubCall stubCall(this, cti_op_bitand);
757         stubCall.addArgument(regT0);
758         stubCall.addArgument(op2, regT2);
759         stubCall.call(result);
760     } else {
761         JITStubCall stubCall(this, cti_op_bitand);
762         stubCall.addArgument(op1, regT2);
763         stubCall.addArgument(regT1);
764         stubCall.call(result);
765     }
766 }
767 
emit_op_post_inc(Instruction * currentInstruction)768 void JIT::emit_op_post_inc(Instruction* currentInstruction)
769 {
770     unsigned result = currentInstruction[1].u.operand;
771     unsigned srcDst = currentInstruction[2].u.operand;
772 
773     emitGetVirtualRegister(srcDst, regT0);
774     move(regT0, regT1);
775     emitJumpSlowCaseIfNotImmediateInteger(regT0);
776     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT1));
777     emitFastArithIntToImmNoCheck(regT1, regT1);
778     emitPutVirtualRegister(srcDst, regT1);
779     emitPutVirtualRegister(result);
780 }
781 
emitSlow_op_post_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)782 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
783 {
784     unsigned result = currentInstruction[1].u.operand;
785     unsigned srcDst = currentInstruction[2].u.operand;
786 
787     linkSlowCase(iter);
788     linkSlowCase(iter);
789     JITStubCall stubCall(this, cti_op_post_inc);
790     stubCall.addArgument(regT0);
791     stubCall.addArgument(Imm32(srcDst));
792     stubCall.call(result);
793 }
794 
emit_op_post_dec(Instruction * currentInstruction)795 void JIT::emit_op_post_dec(Instruction* currentInstruction)
796 {
797     unsigned result = currentInstruction[1].u.operand;
798     unsigned srcDst = currentInstruction[2].u.operand;
799 
800     emitGetVirtualRegister(srcDst, regT0);
801     move(regT0, regT1);
802     emitJumpSlowCaseIfNotImmediateInteger(regT0);
803     addSlowCase(branchSub32(Zero, TrustedImm32(1), regT1));
804     emitFastArithIntToImmNoCheck(regT1, regT1);
805     emitPutVirtualRegister(srcDst, regT1);
806     emitPutVirtualRegister(result);
807 }
808 
emitSlow_op_post_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)809 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
810 {
811     unsigned result = currentInstruction[1].u.operand;
812     unsigned srcDst = currentInstruction[2].u.operand;
813 
814     linkSlowCase(iter);
815     linkSlowCase(iter);
816     JITStubCall stubCall(this, cti_op_post_dec);
817     stubCall.addArgument(regT0);
818     stubCall.addArgument(Imm32(srcDst));
819     stubCall.call(result);
820 }
821 
emit_op_pre_inc(Instruction * currentInstruction)822 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
823 {
824     unsigned srcDst = currentInstruction[1].u.operand;
825 
826     emitGetVirtualRegister(srcDst, regT0);
827     emitJumpSlowCaseIfNotImmediateInteger(regT0);
828     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
829     emitFastArithIntToImmNoCheck(regT0, regT0);
830     emitPutVirtualRegister(srcDst);
831 }
832 
emitSlow_op_pre_inc(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)833 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
834 {
835     unsigned srcDst = currentInstruction[1].u.operand;
836 
837     Jump notImm = getSlowCase(iter);
838     linkSlowCase(iter);
839     emitGetVirtualRegister(srcDst, regT0);
840     notImm.link(this);
841     JITStubCall stubCall(this, cti_op_pre_inc);
842     stubCall.addArgument(regT0);
843     stubCall.call(srcDst);
844 }
845 
emit_op_pre_dec(Instruction * currentInstruction)846 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
847 {
848     unsigned srcDst = currentInstruction[1].u.operand;
849 
850     emitGetVirtualRegister(srcDst, regT0);
851     emitJumpSlowCaseIfNotImmediateInteger(regT0);
852     addSlowCase(branchSub32(Zero, TrustedImm32(1), regT0));
853     emitFastArithIntToImmNoCheck(regT0, regT0);
854     emitPutVirtualRegister(srcDst);
855 }
856 
emitSlow_op_pre_dec(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)857 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
858 {
859     unsigned srcDst = currentInstruction[1].u.operand;
860 
861     Jump notImm = getSlowCase(iter);
862     linkSlowCase(iter);
863     emitGetVirtualRegister(srcDst, regT0);
864     notImm.link(this);
865     JITStubCall stubCall(this, cti_op_pre_dec);
866     stubCall.addArgument(regT0);
867     stubCall.call(srcDst);
868 }
869 
870 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
871 
872 #if CPU(X86) || CPU(X86_64) || CPU(MIPS)
873 
emit_op_mod(Instruction * currentInstruction)874 void JIT::emit_op_mod(Instruction* currentInstruction)
875 {
876     unsigned result = currentInstruction[1].u.operand;
877     unsigned op1 = currentInstruction[2].u.operand;
878     unsigned op2 = currentInstruction[3].u.operand;
879 
880 #if CPU(X86) || CPU(X86_64)
881     // Make sure registers are correct for x86 IDIV instructions.
882     ASSERT(regT0 == X86Registers::eax);
883     ASSERT(regT1 == X86Registers::edx);
884     ASSERT(regT2 == X86Registers::ecx);
885 #endif
886 
887     emitGetVirtualRegisters(op1, regT0, op2, regT2);
888     emitJumpSlowCaseIfNotImmediateInteger(regT0);
889     emitJumpSlowCaseIfNotImmediateInteger(regT2);
890 
891     addSlowCase(branchPtr(Equal, regT2, TrustedImmPtr(JSValue::encode(jsNumber(0)))));
892     m_assembler.cdq();
893     m_assembler.idivl_r(regT2);
894     emitFastArithReTagImmediate(regT1, regT0);
895     emitPutVirtualRegister(result);
896 }
897 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)898 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
899 {
900     unsigned result = currentInstruction[1].u.operand;
901 
902     linkSlowCase(iter);
903     linkSlowCase(iter);
904     linkSlowCase(iter);
905     JITStubCall stubCall(this, cti_op_mod);
906     stubCall.addArgument(regT0);
907     stubCall.addArgument(regT2);
908     stubCall.call(result);
909 }
910 
911 #else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
912 
emit_op_mod(Instruction * currentInstruction)913 void JIT::emit_op_mod(Instruction* currentInstruction)
914 {
915     unsigned result = currentInstruction[1].u.operand;
916     unsigned op1 = currentInstruction[2].u.operand;
917     unsigned op2 = currentInstruction[3].u.operand;
918 
919     JITStubCall stubCall(this, cti_op_mod);
920     stubCall.addArgument(op1, regT2);
921     stubCall.addArgument(op2, regT2);
922     stubCall.call(result);
923 }
924 
emitSlow_op_mod(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)925 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
926 {
927 #if ENABLE(JIT_USE_SOFT_MODULO)
928     unsigned result = currentInstruction[1].u.operand;
929     unsigned op1 = currentInstruction[2].u.operand;
930     unsigned op2 = currentInstruction[3].u.operand;
931     linkSlowCase(iter);
932     linkSlowCase(iter);
933     linkSlowCase(iter);
934     JITStubCall stubCall(this, cti_op_mod);
935     stubCall.addArgument(op1, regT2);
936     stubCall.addArgument(op2, regT2);
937     stubCall.call(result);
938 #else
939     ASSERT_NOT_REACHED();
940 #endif
941 }
942 
943 #endif // CPU(X86) || CPU(X86_64)
944 
945 /* ------------------------------ END: OP_MOD ------------------------------ */
946 
947 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
948 
compileBinaryArithOp(OpcodeID opcodeID,unsigned,unsigned op1,unsigned op2,OperandTypes)949 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
950 {
951     emitGetVirtualRegisters(op1, regT0, op2, regT1);
952     emitJumpSlowCaseIfNotImmediateInteger(regT0);
953     emitJumpSlowCaseIfNotImmediateInteger(regT1);
954     if (opcodeID == op_add)
955         addSlowCase(branchAdd32(Overflow, regT1, regT0));
956     else if (opcodeID == op_sub)
957         addSlowCase(branchSub32(Overflow, regT1, regT0));
958     else {
959         ASSERT(opcodeID == op_mul);
960         addSlowCase(branchMul32(Overflow, regT1, regT0));
961         addSlowCase(branchTest32(Zero, regT0));
962     }
963     emitFastArithIntToImmNoCheck(regT0, regT0);
964 }
965 
compileBinaryArithOpSlowCase(OpcodeID opcodeID,Vector<SlowCaseEntry>::iterator & iter,unsigned result,unsigned op1,unsigned op2,OperandTypes types,bool op1HasImmediateIntFastCase,bool op2HasImmediateIntFastCase)966 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
967 {
968     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
969     COMPILE_ASSERT(((TagTypeNumber + DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
970 
971     Jump notImm1;
972     Jump notImm2;
973     if (op1HasImmediateIntFastCase) {
974         notImm2 = getSlowCase(iter);
975     } else if (op2HasImmediateIntFastCase) {
976         notImm1 = getSlowCase(iter);
977     } else {
978         notImm1 = getSlowCase(iter);
979         notImm2 = getSlowCase(iter);
980     }
981 
982     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
983     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
984         linkSlowCase(iter);
985     emitGetVirtualRegister(op1, regT0);
986 
987     Label stubFunctionCall(this);
988     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
989     if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) {
990         emitGetVirtualRegister(op1, regT0);
991         emitGetVirtualRegister(op2, regT1);
992     }
993     stubCall.addArgument(regT0);
994     stubCall.addArgument(regT1);
995     stubCall.call(result);
996     Jump end = jump();
997 
998     if (op1HasImmediateIntFastCase) {
999         notImm2.link(this);
1000         if (!types.second().definitelyIsNumber())
1001             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1002         emitGetVirtualRegister(op1, regT1);
1003         convertInt32ToDouble(regT1, fpRegT1);
1004         addPtr(tagTypeNumberRegister, regT0);
1005         movePtrToDouble(regT0, fpRegT2);
1006     } else if (op2HasImmediateIntFastCase) {
1007         notImm1.link(this);
1008         if (!types.first().definitelyIsNumber())
1009             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1010         emitGetVirtualRegister(op2, regT1);
1011         convertInt32ToDouble(regT1, fpRegT1);
1012         addPtr(tagTypeNumberRegister, regT0);
1013         movePtrToDouble(regT0, fpRegT2);
1014     } else {
1015         // if we get here, eax is not an int32, edx not yet checked.
1016         notImm1.link(this);
1017         if (!types.first().definitelyIsNumber())
1018             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
1019         if (!types.second().definitelyIsNumber())
1020             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
1021         addPtr(tagTypeNumberRegister, regT0);
1022         movePtrToDouble(regT0, fpRegT1);
1023         Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
1024         convertInt32ToDouble(regT1, fpRegT2);
1025         Jump op2wasInteger = jump();
1026 
1027         // if we get here, eax IS an int32, edx is not.
1028         notImm2.link(this);
1029         if (!types.second().definitelyIsNumber())
1030             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
1031         convertInt32ToDouble(regT0, fpRegT1);
1032         op2isDouble.link(this);
1033         addPtr(tagTypeNumberRegister, regT1);
1034         movePtrToDouble(regT1, fpRegT2);
1035         op2wasInteger.link(this);
1036     }
1037 
1038     if (opcodeID == op_add)
1039         addDouble(fpRegT2, fpRegT1);
1040     else if (opcodeID == op_sub)
1041         subDouble(fpRegT2, fpRegT1);
1042     else if (opcodeID == op_mul)
1043         mulDouble(fpRegT2, fpRegT1);
1044     else {
1045         ASSERT(opcodeID == op_div);
1046         divDouble(fpRegT2, fpRegT1);
1047     }
1048     moveDoubleToPtr(fpRegT1, regT0);
1049     subPtr(tagTypeNumberRegister, regT0);
1050     emitPutVirtualRegister(result, regT0);
1051 
1052     end.link(this);
1053 }
1054 
emit_op_add(Instruction * currentInstruction)1055 void JIT::emit_op_add(Instruction* currentInstruction)
1056 {
1057     unsigned result = currentInstruction[1].u.operand;
1058     unsigned op1 = currentInstruction[2].u.operand;
1059     unsigned op2 = currentInstruction[3].u.operand;
1060     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1061 
1062     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
1063         JITStubCall stubCall(this, cti_op_add);
1064         stubCall.addArgument(op1, regT2);
1065         stubCall.addArgument(op2, regT2);
1066         stubCall.call(result);
1067         return;
1068     }
1069 
1070     if (isOperandConstantImmediateInt(op1)) {
1071         emitGetVirtualRegister(op2, regT0);
1072         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1073         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
1074         emitFastArithIntToImmNoCheck(regT0, regT0);
1075     } else if (isOperandConstantImmediateInt(op2)) {
1076         emitGetVirtualRegister(op1, regT0);
1077         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1078         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
1079         emitFastArithIntToImmNoCheck(regT0, regT0);
1080     } else
1081         compileBinaryArithOp(op_add, result, op1, op2, types);
1082 
1083     emitPutVirtualRegister(result);
1084 }
1085 
emitSlow_op_add(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1086 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1087 {
1088     unsigned result = currentInstruction[1].u.operand;
1089     unsigned op1 = currentInstruction[2].u.operand;
1090     unsigned op2 = currentInstruction[3].u.operand;
1091     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1092 
1093     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
1094         return;
1095 
1096     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
1097     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
1098     compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
1099 }
1100 
emit_op_mul(Instruction * currentInstruction)1101 void JIT::emit_op_mul(Instruction* currentInstruction)
1102 {
1103     unsigned result = currentInstruction[1].u.operand;
1104     unsigned op1 = currentInstruction[2].u.operand;
1105     unsigned op2 = currentInstruction[3].u.operand;
1106     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1107 
1108     // For now, only plant a fast int case if the constant operand is greater than zero.
1109     int32_t value;
1110     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
1111         emitGetVirtualRegister(op2, regT0);
1112         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1113         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1114         emitFastArithReTagImmediate(regT0, regT0);
1115     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
1116         emitGetVirtualRegister(op1, regT0);
1117         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1118         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
1119         emitFastArithReTagImmediate(regT0, regT0);
1120     } else
1121         compileBinaryArithOp(op_mul, result, op1, op2, types);
1122 
1123     emitPutVirtualRegister(result);
1124 }
1125 
emitSlow_op_mul(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1126 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1127 {
1128     unsigned result = currentInstruction[1].u.operand;
1129     unsigned op1 = currentInstruction[2].u.operand;
1130     unsigned op2 = currentInstruction[3].u.operand;
1131     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1132 
1133     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
1134     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
1135     compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
1136 }
1137 
emit_op_div(Instruction * currentInstruction)1138 void JIT::emit_op_div(Instruction* currentInstruction)
1139 {
1140     unsigned dst = currentInstruction[1].u.operand;
1141     unsigned op1 = currentInstruction[2].u.operand;
1142     unsigned op2 = currentInstruction[3].u.operand;
1143     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1144 
1145     if (isOperandConstantImmediateDouble(op1)) {
1146         emitGetVirtualRegister(op1, regT0);
1147         addPtr(tagTypeNumberRegister, regT0);
1148         movePtrToDouble(regT0, fpRegT0);
1149     } else if (isOperandConstantImmediateInt(op1)) {
1150         emitLoadInt32ToDouble(op1, fpRegT0);
1151     } else {
1152         emitGetVirtualRegister(op1, regT0);
1153         if (!types.first().definitelyIsNumber())
1154             emitJumpSlowCaseIfNotImmediateNumber(regT0);
1155         Jump notInt = emitJumpIfNotImmediateInteger(regT0);
1156         convertInt32ToDouble(regT0, fpRegT0);
1157         Jump skipDoubleLoad = jump();
1158         notInt.link(this);
1159         addPtr(tagTypeNumberRegister, regT0);
1160         movePtrToDouble(regT0, fpRegT0);
1161         skipDoubleLoad.link(this);
1162     }
1163 
1164     if (isOperandConstantImmediateDouble(op2)) {
1165         emitGetVirtualRegister(op2, regT1);
1166         addPtr(tagTypeNumberRegister, regT1);
1167         movePtrToDouble(regT1, fpRegT1);
1168     } else if (isOperandConstantImmediateInt(op2)) {
1169         emitLoadInt32ToDouble(op2, fpRegT1);
1170     } else {
1171         emitGetVirtualRegister(op2, regT1);
1172         if (!types.second().definitelyIsNumber())
1173             emitJumpSlowCaseIfNotImmediateNumber(regT1);
1174         Jump notInt = emitJumpIfNotImmediateInteger(regT1);
1175         convertInt32ToDouble(regT1, fpRegT1);
1176         Jump skipDoubleLoad = jump();
1177         notInt.link(this);
1178         addPtr(tagTypeNumberRegister, regT1);
1179         movePtrToDouble(regT1, fpRegT1);
1180         skipDoubleLoad.link(this);
1181     }
1182     divDouble(fpRegT1, fpRegT0);
1183 
1184     // Double result.
1185     moveDoubleToPtr(fpRegT0, regT0);
1186     subPtr(tagTypeNumberRegister, regT0);
1187 
1188     emitPutVirtualRegister(dst, regT0);
1189 }
1190 
emitSlow_op_div(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1191 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1192 {
1193     unsigned result = currentInstruction[1].u.operand;
1194     unsigned op1 = currentInstruction[2].u.operand;
1195     unsigned op2 = currentInstruction[3].u.operand;
1196     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1197     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
1198 #ifndef NDEBUG
1199         breakpoint();
1200 #endif
1201         return;
1202     }
1203     if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
1204         if (!types.first().definitelyIsNumber())
1205             linkSlowCase(iter);
1206     }
1207     if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
1208         if (!types.second().definitelyIsNumber())
1209             linkSlowCase(iter);
1210     }
1211     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1212     JITStubCall stubCall(this, cti_op_div);
1213     stubCall.addArgument(op1, regT2);
1214     stubCall.addArgument(op2, regT2);
1215     stubCall.call(result);
1216 }
1217 
emit_op_sub(Instruction * currentInstruction)1218 void JIT::emit_op_sub(Instruction* currentInstruction)
1219 {
1220     unsigned result = currentInstruction[1].u.operand;
1221     unsigned op1 = currentInstruction[2].u.operand;
1222     unsigned op2 = currentInstruction[3].u.operand;
1223     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1224 
1225     compileBinaryArithOp(op_sub, result, op1, op2, types);
1226     emitPutVirtualRegister(result);
1227 }
1228 
emitSlow_op_sub(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1229 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1230 {
1231     unsigned result = currentInstruction[1].u.operand;
1232     unsigned op1 = currentInstruction[2].u.operand;
1233     unsigned op2 = currentInstruction[3].u.operand;
1234     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1235 
1236     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
1237 }
1238 
1239 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
1240 
1241 } // namespace JSC
1242 
1243 #endif // USE(JSVALUE64)
1244 #endif // ENABLE(JIT)
1245