Home | History | Annotate | Download | only in jit
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    705 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
    706 {
    707     emit_op_jlesseq(currentInstruction, true);
    708 }
    709 
    710 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    711 {
    712     emitSlow_op_jlesseq(currentInstruction, iter, true);
    713 }
    714 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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