Changeset 39540 in webkit for trunk/JavaScriptCore/jit


Ignore:
Timestamp:
Jan 1, 2009, 7:06:10 PM (16 years ago)
Author:
[email protected]
Message:

2009-01-01 Gavin Barraclough <[email protected]>

Reviewed by Darin Adler.

Allow 32-bit integers to be stored in JSImmediates, on x64-bit.
Presently the top 32-bits of a 64-bit JSImmediate serve as a sign extension of a 31-bit
int stored in the low word (shifted left by one, to make room for a tag). In the new
format, the top 31-bits serve as a sign extension of a 32-bit int, still shifted left by
one.

The new behavior is enabled using a flag in Platform.h, 'WTF_USE_ALTERNATE_JSIMMEDIATE'.
When this is set the constants defining the range of ints allowed to be stored as
JSImmediate values is extended. The code in JSImmediate.h can safely operate on either
format. This patch updates the JIT so that it can also operate with the new format.

~2% progression on x86-64, with & without the JIT, on sunspider & v8 tests.

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::addPtr): (JSC::MacroAssembler::orPtr): (JSC::MacroAssembler::or32): (JSC::MacroAssembler::rshiftPtr): (JSC::MacroAssembler::rshift32): (JSC::MacroAssembler::subPtr): (JSC::MacroAssembler::xorPtr): (JSC::MacroAssembler::xor32): (JSC::MacroAssembler::move): (JSC::MacroAssembler::compareImm64ForBranch): (JSC::MacroAssembler::compareImm64ForBranchEquality): (JSC::MacroAssembler::jePtr): (JSC::MacroAssembler::jgePtr): (JSC::MacroAssembler::jlPtr): (JSC::MacroAssembler::jlePtr): (JSC::MacroAssembler::jnePtr): (JSC::MacroAssembler::jnzSubPtr): (JSC::MacroAssembler::joAddPtr): (JSC::MacroAssembler::jzSubPtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::addq_rr): (JSC::X86Assembler::orq_ir): (JSC::X86Assembler::subq_ir): (JSC::X86Assembler::xorq_rr): (JSC::X86Assembler::sarq_CLr): (JSC::X86Assembler::sarq_i8r): (JSC::X86Assembler::cmpq_ir):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq): (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArith_op_lshift): (JSC::JIT::compileFastArithSlow_op_lshift): (JSC::JIT::compileFastArith_op_rshift): (JSC::JIT::compileFastArithSlow_op_rshift): (JSC::JIT::compileFastArith_op_bitand): (JSC::JIT::compileFastArithSlow_op_bitand): (JSC::JIT::compileFastArith_op_mod): (JSC::JIT::compileFastArithSlow_op_mod): (JSC::JIT::compileFastArith_op_add): (JSC::JIT::compileFastArithSlow_op_add): (JSC::JIT::compileFastArith_op_mul): (JSC::JIT::compileFastArithSlow_op_mul): (JSC::JIT::compileFastArith_op_post_inc): (JSC::JIT::compileFastArithSlow_op_post_inc): (JSC::JIT::compileFastArith_op_post_dec): (JSC::JIT::compileFastArithSlow_op_post_dec): (JSC::JIT::compileFastArith_op_pre_inc): (JSC::JIT::compileFastArithSlow_op_pre_inc): (JSC::JIT::compileFastArith_op_pre_dec): (JSC::JIT::compileFastArithSlow_op_pre_dec): (JSC::JIT::compileBinaryArithOp):
  • jit/JITInlineMethods.h: (JSC::JIT::getConstantOperand): (JSC::JIT::getConstantOperandImmediateInt): (JSC::JIT::isOperandConstantImmediateInt): (JSC::JIT::isOperandConstant31BitImmediateInt): (JSC::JIT::emitFastArithDeTagImmediate): (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): (JSC::JIT::emitFastArithReTagImmediate): (JSC::JIT::emitFastArithImmToInt): (JSC::JIT::emitFastArithIntToImmNoCheck):
  • runtime/JSImmediate.h: (JSC::JSImmediate::isPositiveNumber): (JSC::JSImmediate::isNegative): (JSC::JSImmediate::rightShiftImmediateNumbers): (JSC::JSImmediate::canDoFastAdditiveOperations): (JSC::JSImmediate::makeValue): (JSC::JSImmediate::makeInt): (JSC::JSImmediate::makeBool): (JSC::JSImmediate::intValue): (JSC::JSImmediate::rawValue): (JSC::JSImmediate::toBoolean): (JSC::JSImmediate::from):
  • wtf/Platform.h:
Location:
trunk/JavaScriptCore/jit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/jit/JIT.cpp

    r39524 r39540  
    228228
    229229    // They are equal - set the result to true. (Or false, if negated).
    230     move(Imm32(asInteger(jsBoolean(!negated))), X86::eax);
     230    move(ImmPtr(jsBoolean(!negated)), X86::eax);
    231231    Jump bothWereImmediatesAndEqual = jump();
    232232
     
    236236    firstNotImmediate.link(this);
    237237    emitJumpSlowCaseIfJSCell(X86::edx);
    238     addSlowCase(je32(X86::edx, Imm32(asInteger(JSImmediate::zeroImmediate()))));
     238    addSlowCase(jePtr(X86::edx, ImmPtr(JSImmediate::zeroImmediate())));
    239239    Jump firstWasNotImmediate = jump();
    240240
     
    242242    // If eax is 0 jump to a slow case, otherwise these values are not equal.
    243243    secondNotImmediate.link(this);
    244     addSlowCase(je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate()))));
     244    addSlowCase(jePtr(X86::eax, ImmPtr(JSImmediate::zeroImmediate())));
    245245
    246246    // We get here if the two values are different immediates, or one is 0 and the other is a JSCell.
     
    248248    bothWereImmediatesButNotEqual.link(this);
    249249    firstWasNotImmediate.link(this);
    250     move(Imm32(asInteger(jsBoolean(negated))), X86::eax);
     250    move(ImmPtr(jsBoolean(negated)), X86::eax);
    251251   
    252252    bothWereImmediatesAndEqual.link(this);
     
    313313        }
    314314        case op_add: {
    315             unsigned dst = currentInstruction[1].u.operand;
    316             unsigned src1 = currentInstruction[2].u.operand;
    317             unsigned src2 = currentInstruction[3].u.operand;
    318 
    319             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
    320                 emitGetVirtualRegister(src2, X86::eax);
    321                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    322                 addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax));
    323                 signExtend32ToPtr(X86::eax, X86::eax);
    324                 emitPutVirtualRegister(dst);
    325             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
    326                 emitGetVirtualRegister(src1, X86::eax);
    327                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    328                 addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax));
    329                 signExtend32ToPtr(X86::eax, X86::eax);
    330                 emitPutVirtualRegister(dst);
    331             } else {
    332                 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    333                 if (types.first().mightBeNumber() && types.second().mightBeNumber())
    334                     compileBinaryArithOp(op_add, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
    335                 else {
    336                     emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
    337                     emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
    338                     emitCTICall(Interpreter::cti_op_add);
    339                     emitPutVirtualRegister(currentInstruction[1].u.operand);
    340                 }
    341             }
     315            compileFastArith_op_add(currentInstruction);
    342316            NEXT_OPCODE(op_add);
    343317        }
     
    356330        }
    357331        case op_pre_inc: {
    358             int srcDst = currentInstruction[1].u.operand;
    359             emitGetVirtualRegister(srcDst, X86::eax);
    360             emitJumpSlowCaseIfNotImmNum(X86::eax);
    361             addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax));
    362             signExtend32ToPtr(X86::eax, X86::eax);
    363             emitPutVirtualRegister(srcDst);
     332            compileFastArith_op_pre_inc(currentInstruction[1].u.operand);
    364333            NEXT_OPCODE(op_pre_inc);
    365334        }
     
    374343            emitSlowScriptCheck();
    375344
     345            unsigned op1 = currentInstruction[1].u.operand;
     346            unsigned op2 = currentInstruction[2].u.operand;
    376347            unsigned target = currentInstruction[3].u.operand;
    377             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
    378             if (src2imm) {
    379                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
     348            if (isOperandConstantImmediateInt(op2)) {
     349                emitGetVirtualRegister(op1, X86::eax);
    380350                emitJumpSlowCaseIfNotImmNum(X86::eax);
    381                 addJump(jl32(X86::eax, Imm32(asInteger(src2imm))), target + 3);
     351                addJump(jlPtr(X86::eax, ImmPtr(getConstantOperand(op2))), target + 3);
    382352            } else {
    383                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
     353                emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
    384354                emitJumpSlowCaseIfNotImmNum(X86::eax);
    385355                emitJumpSlowCaseIfNotImmNum(X86::edx);
    386                 addJump(jl32(X86::eax, X86::edx), target + 3);
     356                addJump(jlPtr(X86::eax, X86::edx), target + 3);
    387357            }
    388358            NEXT_OPCODE(op_loop_if_less);
     
    391361            emitSlowScriptCheck();
    392362
     363            unsigned op1 = currentInstruction[1].u.operand;
     364            unsigned op2 = currentInstruction[2].u.operand;
    393365            unsigned target = currentInstruction[3].u.operand;
    394             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
    395             if (src2imm) {
    396                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
     366            if (isOperandConstantImmediateInt(op2)) {
     367                emitGetVirtualRegister(op1, X86::eax);
    397368                emitJumpSlowCaseIfNotImmNum(X86::eax);
    398                 addJump(jle32(X86::eax, Imm32(asInteger(src2imm))), target + 3);
     369                addJump(jlePtr(X86::eax, ImmPtr(getConstantOperand(op2))), target + 3);
    399370            } else {
    400                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
     371                emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
    401372                emitJumpSlowCaseIfNotImmNum(X86::eax);
    402373                emitJumpSlowCaseIfNotImmNum(X86::edx);
    403                 addJump(jle32(X86::eax, X86::edx), target + 3);
     374                addJump(jlePtr(X86::eax, X86::edx), target + 3);
    404375            }
    405             NEXT_OPCODE(op_loop_if_lesseq);
     376            NEXT_OPCODE(op_loop_if_less);
    406377        }
    407378        case op_new_object: {
     
    449420
    450421            // optimistically load true result
    451             move(Imm32(asInteger(jsBoolean(true))), X86::eax);
     422            move(ImmPtr(jsBoolean(true)), X86::eax);
    452423
    453424            Label loop(this);
     
    459430            Jump exit = jePtr(X86::ecx, X86::edx);
    460431
    461             jne32(X86::ecx, Imm32(asInteger(jsNull())), loop);
    462 
    463             move(Imm32(asInteger(jsBoolean(false))), X86::eax);
     432            jnePtr(X86::ecx, ImmPtr(jsNull()), loop);
     433
     434            move(ImmPtr(jsBoolean(false)), X86::eax);
    464435
    465436            exit.link(this);
     
    478449        }
    479450        case op_mul: {
    480             unsigned dst = currentInstruction[1].u.operand;
    481             unsigned src1 = currentInstruction[2].u.operand;
    482             unsigned src2 = currentInstruction[3].u.operand;
    483 
    484             // For now, only plant a fast int case if the constant operand is greater than zero.
    485             JSValue* src1Value = getConstantImmediateNumericArg(src1);
    486             JSValue* src2Value = getConstantImmediateNumericArg(src2);
    487             int32_t value;
    488             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
    489                 emitGetVirtualRegister(src2, X86::eax);
    490                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    491                 emitFastArithDeTagImmediate(X86::eax);
    492                 addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
    493                 emitFastArithReTagImmediate(X86::eax);
    494                 emitPutVirtualRegister(dst);
    495             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
    496                 emitGetVirtualRegister(src1, X86::eax);
    497                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    498                 emitFastArithDeTagImmediate(X86::eax);
    499                 addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
    500                 emitFastArithReTagImmediate(X86::eax);
    501                 emitPutVirtualRegister(dst);
    502             } else
    503                 compileBinaryArithOp(op_mul, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
    504 
     451            compileFastArith_op_mul(currentInstruction);
    505452            NEXT_OPCODE(op_mul);
    506453        }
     
    672619            emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
    673620
    674             Jump isZero = je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate())));
     621            Jump isZero = jePtr(X86::eax, ImmPtr(JSImmediate::zeroImmediate()));
    675622            addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
    676623
    677             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))), target + 2);
    678             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))));
     624            addJump(jePtr(X86::eax, ImmPtr(jsBoolean(true))), target + 2);
     625            addSlowCase(jnePtr(X86::eax, ImmPtr(jsBoolean(false))));
    679626
    680627            isZero.link(this);
     
    735682        CTI_COMPILE_BINARY_OP(op_div)
    736683        case op_pre_dec: {
    737             int srcDst = currentInstruction[1].u.operand;
    738             emitGetVirtualRegister(srcDst, X86::eax);
    739             emitJumpSlowCaseIfNotImmNum(X86::eax);
    740             addSlowCase(joSub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax));
    741             signExtend32ToPtr(X86::eax, X86::eax);
    742             emitPutVirtualRegister(srcDst);
     684            compileFastArith_op_pre_dec(currentInstruction[1].u.operand);
    743685            NEXT_OPCODE(op_pre_dec);
    744686        }
    745687        case op_jnless: {
     688            unsigned op1 = currentInstruction[1].u.operand;
     689            unsigned op2 = currentInstruction[2].u.operand;
    746690            unsigned target = currentInstruction[3].u.operand;
    747             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
    748             if (src2imm) {
    749                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::edx);
    750                 emitJumpSlowCaseIfNotImmNum(X86::edx);
    751                 addJump(jge32(X86::edx, Imm32(asInteger(src2imm))), target + 3);
     691            if (isOperandConstantImmediateInt(op2)) {
     692                emitGetVirtualRegister(op1, X86::eax);
     693                emitJumpSlowCaseIfNotImmNum(X86::eax);
     694                addJump(jgePtr(X86::eax, ImmPtr(getConstantOperand(op2))), target + 3);
    752695            } else {
    753                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
     696                emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
    754697                emitJumpSlowCaseIfNotImmNum(X86::eax);
    755698                emitJumpSlowCaseIfNotImmNum(X86::edx);
    756                 addJump(jge32(X86::eax, X86::edx), target + 3);
     699                addJump(jgePtr(X86::eax, X86::edx), target + 3);
    757700            }
    758701            NEXT_OPCODE(op_jnless);
     
    770713            emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
    771714
    772             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate()))), target + 2);
     715            addJump(jePtr(X86::eax, ImmPtr(JSImmediate::zeroImmediate())), target + 2);
    773716            Jump isNonZero = jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger));
    774717
    775             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))), target + 2);
    776             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))));
     718            addJump(jePtr(X86::eax, ImmPtr(jsBoolean(false))), target + 2);
     719            addSlowCase(jnePtr(X86::eax, ImmPtr(jsBoolean(true))));
    777720
    778721            isNonZero.link(this);
     
    794737            isImmediate.link(this);
    795738            and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
    796             addJump(je32(X86::eax, Imm32(asInteger(jsNull()))), target + 2);           
     739            addJump(jePtr(X86::eax, ImmPtr(jsNull())), target + 2);           
    797740
    798741            wasNotImmediate.link(this);
     
    814757            isImmediate.link(this);
    815758            and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
    816             addJump(jne32(X86::eax, Imm32(asInteger(jsNull()))), target + 2);           
     759            addJump(jnePtr(X86::eax, ImmPtr(jsNull())), target + 2);           
    817760
    818761            wasNotImmediate.link(this);
     
    820763        }
    821764        case op_post_inc: {
    822             int srcDst = currentInstruction[2].u.operand;
    823             emitGetVirtualRegister(srcDst, X86::eax);
    824             move(X86::eax, X86::edx);
    825             emitJumpSlowCaseIfNotImmNum(X86::eax);
    826             addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::edx));
    827             signExtend32ToPtr(X86::edx, X86::edx);
    828             emitPutVirtualRegister(srcDst, X86::edx);
    829             emitPutVirtualRegister(currentInstruction[1].u.operand);
     765            compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand);
    830766            NEXT_OPCODE(op_post_inc);
    831767        }
     
    857793        }
    858794        case op_lshift: {
    859             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
    860             emitJumpSlowCaseIfNotImmNum(X86::eax);
    861             emitJumpSlowCaseIfNotImmNum(X86::ecx);
    862             emitFastArithImmToInt(X86::eax);
    863             emitFastArithImmToInt(X86::ecx);
    864             lshift32(X86::ecx, X86::eax);
    865             emitFastArithIntToImmOrSlowCase(X86::eax);
    866             emitPutVirtualRegister(currentInstruction[1].u.operand);
     795            compileFastArith_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
    867796            NEXT_OPCODE(op_lshift);
    868797        }
    869798        case op_bitand: {
    870             unsigned src1 = currentInstruction[2].u.operand;
    871             unsigned src2 = currentInstruction[3].u.operand;
    872             unsigned dst = currentInstruction[1].u.operand;
    873             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
    874                 emitGetVirtualRegister(src2, X86::eax);
    875                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    876                 andPtr(Imm32(asInteger(value)), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
    877                 emitPutVirtualRegister(dst);
    878             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
    879                 emitGetVirtualRegister(src1, X86::eax);
    880                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    881                 andPtr(Imm32(asInteger(value)), X86::eax);
    882                 emitPutVirtualRegister(dst);
    883             } else {
    884                 emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
    885                 andPtr(X86::edx, X86::eax);
    886                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    887                 emitPutVirtualRegister(dst);
    888             }
     799            compileFastArith_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
    889800            NEXT_OPCODE(op_bitand);
    890801        }
    891802        case op_rshift: {
    892             unsigned src1 = currentInstruction[2].u.operand;
    893             unsigned src2 = currentInstruction[3].u.operand;
    894             if (JSValue* value = getConstantImmediateNumericArg(src2)) {
    895                 emitGetVirtualRegister(src1, X86::eax);
    896                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    897                 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
    898                 rshift32(Imm32(JSImmediate::getTruncatedUInt32(value) & 0x1f), X86::eax);
    899             } else {
    900                 emitGetVirtualRegisters(src1, X86::eax, src2, X86::ecx);
    901                 emitJumpSlowCaseIfNotImmNum(X86::eax);
    902                 emitJumpSlowCaseIfNotImmNum(X86::ecx);
    903                 emitFastArithImmToInt(X86::ecx);
    904                 rshift32(X86::ecx, X86::eax);
    905             }
    906             emitFastArithPotentiallyReTagImmediate(X86::eax);
    907             emitPutVirtualRegister(currentInstruction[1].u.operand);
     803            compileFastArith_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
    908804            NEXT_OPCODE(op_rshift);
    909805        }
     
    931827        }
    932828        case op_mod: {
    933             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
    934             emitJumpSlowCaseIfNotImmNum(X86::eax);
    935             emitJumpSlowCaseIfNotImmNum(X86::ecx);
    936             emitFastArithDeTagImmediate(X86::eax);
    937             addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
    938             mod32(X86::ecx, X86::eax, X86::edx);
    939             emitFastArithReTagImmediate(X86::edx);
    940             move(X86::edx, X86::eax);
    941             emitPutVirtualRegister(currentInstruction[1].u.operand);
     829            compileFastArith_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
    942830            NEXT_OPCODE(op_mod);
    943831        }
     
    946834            emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
    947835
    948             Jump isZero = je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate())));
     836            Jump isZero = jePtr(X86::eax, ImmPtr(JSImmediate::zeroImmediate()));
    949837            addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
    950838
    951             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))), target + 2);
    952             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))));
     839            addJump(jePtr(X86::eax, ImmPtr(jsBoolean(true))), target + 2);
     840            addSlowCase(jnePtr(X86::eax, ImmPtr(jsBoolean(false))));
    953841
    954842            isZero.link(this);
     
    967855        }
    968856        case op_post_dec: {
    969             int srcDst = currentInstruction[2].u.operand;
    970             emitGetVirtualRegister(srcDst, X86::eax);
    971             move(X86::eax, X86::edx);
    972             emitJumpSlowCaseIfNotImmNum(X86::eax);
    973             addSlowCase(joSub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::edx));
    974             signExtend32ToPtr(X86::edx, X86::edx);
    975             emitPutVirtualRegister(srcDst, X86::edx);
    976             emitPutVirtualRegister(currentInstruction[1].u.operand);
     857            compileFastArith_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand);
    977858            NEXT_OPCODE(op_post_dec);
    978859        }
     
    981862            emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
    982863            emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
    983             xor32(X86::edx, X86::eax);
     864            xorPtr(X86::edx, X86::eax);
    984865            emitFastArithReTagImmediate(X86::eax);
    985866            emitPutVirtualRegister(currentInstruction[1].u.operand);
     
    13551236        }
    13561237        case op_add: {
    1357             unsigned dst = currentInstruction[1].u.operand;
    1358             unsigned src1 = currentInstruction[2].u.operand;
    1359             unsigned src2 = currentInstruction[3].u.operand;
    1360             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
    1361                 Jump notImm = getSlowCase(iter);
    1362                 linkSlowCase(iter);
    1363                 sub32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax);
    1364                 notImm.link(this);
    1365                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
    1366                 emitPutJITStubArg(X86::eax, 2);
    1367                 emitCTICall(Interpreter::cti_op_add);
    1368                 emitPutVirtualRegister(dst);
    1369             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
    1370                 Jump notImm = getSlowCase(iter);
    1371                 linkSlowCase(iter);
    1372                 sub32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax);
    1373                 notImm.link(this);
    1374                 emitPutJITStubArg(X86::eax, 1);
    1375                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
    1376                 emitCTICall(Interpreter::cti_op_add);
    1377                 emitPutVirtualRegister(dst);
    1378             } else {
    1379                 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    1380                 ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
    1381                 compileBinaryArithOpSlowCase(op_add, iter, dst, src1, src2, types);
    1382             }
    1383 
     1238            compileFastArithSlow_op_add(currentInstruction, iter);
    13841239            NEXT_OPCODE(op_add);
    13851240        }
     
    14261281        }
    14271282        case op_rshift: {
    1428             unsigned src2 = currentInstruction[3].u.operand;
    1429             linkSlowCase(iter);
    1430             if (getConstantImmediateNumericArg(src2))
    1431                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
    1432             else {
    1433                 linkSlowCase(iter);
    1434                 emitPutJITStubArg(X86::ecx, 2);
    1435             }
    1436 
    1437             emitPutJITStubArg(X86::eax, 1);
    1438             emitCTICall(Interpreter::cti_op_rshift);
    1439             emitPutVirtualRegister(currentInstruction[1].u.operand);
     1283            compileFastArithSlow_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
    14401284            NEXT_OPCODE(op_rshift);
    14411285        }
    14421286        case op_lshift: {
    1443             Jump notImm1 = getSlowCase(iter);
    1444             Jump notImm2 = getSlowCase(iter);
    1445             linkSlowCase(iter);
    1446             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
    1447             notImm1.link(this);
    1448             notImm2.link(this);
    1449             emitPutJITStubArg(X86::eax, 1);
    1450             emitPutJITStubArg(X86::ecx, 2);
    1451             emitCTICall(Interpreter::cti_op_lshift);
    1452             emitPutVirtualRegister(currentInstruction[1].u.operand);
     1287            compileFastArithSlow_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
    14531288            NEXT_OPCODE(op_lshift);
    14541289        }
     
    15001335        }
    15011336        case op_pre_inc: {
    1502             unsigned srcDst = currentInstruction[1].u.operand;
    1503             Jump notImm = getSlowCase(iter);
    1504             linkSlowCase(iter);
    1505             sub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax);
    1506             notImm.link(this);
    1507             emitPutJITStubArg(X86::eax, 1);
    1508             emitCTICall(Interpreter::cti_op_pre_inc);
    1509             emitPutVirtualRegister(srcDst);
     1337            compileFastArithSlow_op_pre_inc(currentInstruction[1].u.operand, iter);
    15101338            NEXT_OPCODE(op_pre_inc);
    15111339        }
     
    15441372        }
    15451373        case op_pre_dec: {
    1546             unsigned srcDst = currentInstruction[1].u.operand;
    1547             Jump notImm = getSlowCase(iter);
    1548             linkSlowCase(iter);
    1549             add32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax);
    1550             notImm.link(this);
    1551             emitPutJITStubArg(X86::eax, 1);
    1552             emitCTICall(Interpreter::cti_op_pre_dec);
    1553             emitPutVirtualRegister(srcDst);
     1374            compileFastArithSlow_op_pre_dec(currentInstruction[1].u.operand, iter);
    15541375            NEXT_OPCODE(op_pre_dec);
    15551376        }
     
    15591380            if (src2imm) {
    15601381                linkSlowCase(iter);
    1561                 emitPutJITStubArg(X86::edx, 1);
     1382                emitPutJITStubArg(X86::eax, 1);
    15621383                emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
    15631384                emitCTICall(Interpreter::cti_op_jless);
     
    15901411        }
    15911412        case op_post_inc: {
    1592             unsigned srcDst = currentInstruction[2].u.operand;
    1593             linkSlowCase(iter);
    1594             linkSlowCase(iter);
    1595             emitPutJITStubArg(X86::eax, 1);
    1596             emitCTICall(Interpreter::cti_op_post_inc);
    1597             emitPutVirtualRegister(srcDst, X86::edx);
    1598             emitPutVirtualRegister(currentInstruction[1].u.operand);
     1413            compileFastArithSlow_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);
    15991414            NEXT_OPCODE(op_post_inc);
    16001415        }
     
    16071422        }
    16081423        case op_bitand: {
    1609             linkSlowCase(iter);
    1610             unsigned src1 = currentInstruction[2].u.operand;
    1611             unsigned src2 = currentInstruction[3].u.operand;
    1612             unsigned dst = currentInstruction[1].u.operand;
    1613             if (getConstantImmediateNumericArg(src1)) {
    1614                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
    1615                 emitPutJITStubArg(X86::eax, 2);
    1616                 emitCTICall(Interpreter::cti_op_bitand);
    1617                 emitPutVirtualRegister(dst);
    1618             } else if (getConstantImmediateNumericArg(src2)) {
    1619                 emitPutJITStubArg(X86::eax, 1);
    1620                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
    1621                 emitCTICall(Interpreter::cti_op_bitand);
    1622                 emitPutVirtualRegister(dst);
    1623             } else {
    1624                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
    1625                 emitPutJITStubArg(X86::edx, 2);
    1626                 emitCTICall(Interpreter::cti_op_bitand);
    1627                 emitPutVirtualRegister(dst);
    1628             }
     1424            compileFastArithSlow_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
    16291425            NEXT_OPCODE(op_bitand);
    16301426        }
     
    16381434        }
    16391435        case op_post_dec: {
    1640             unsigned srcDst = currentInstruction[2].u.operand;
    1641             linkSlowCase(iter);
    1642             linkSlowCase(iter);
    1643             emitPutJITStubArg(X86::eax, 1);
    1644             emitCTICall(Interpreter::cti_op_post_dec);
    1645             emitPutVirtualRegister(srcDst, X86::edx);
    1646             emitPutVirtualRegister(currentInstruction[1].u.operand);
     1436            compileFastArithSlow_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);
    16471437            NEXT_OPCODE(op_post_dec);
    16481438        }
     
    17111501        }
    17121502        case op_mod: {
    1713             Jump notImm1 = getSlowCase(iter);
    1714             Jump notImm2 = getSlowCase(iter);
    1715             linkSlowCase(iter);
    1716             emitFastArithReTagImmediate(X86::eax);
    1717             emitFastArithReTagImmediate(X86::ecx);
    1718             notImm1.link(this);
    1719             notImm2.link(this);
    1720             emitPutJITStubArg(X86::eax, 1);
    1721             emitPutJITStubArg(X86::ecx, 2);
    1722             emitCTICall(Interpreter::cti_op_mod);
    1723             emitPutVirtualRegister(currentInstruction[1].u.operand);
     1503            compileFastArithSlow_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
    17241504            NEXT_OPCODE(op_mod);
    17251505        }
    17261506        case op_mul: {
    1727             int dst = currentInstruction[1].u.operand;
    1728             int src1 = currentInstruction[2].u.operand;
    1729             int src2 = currentInstruction[3].u.operand;
    1730             JSValue* src1Value = getConstantImmediateNumericArg(src1);
    1731             JSValue* src2Value = getConstantImmediateNumericArg(src2);
    1732             int32_t value;
    1733             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
    1734                 linkSlowCase(iter);
    1735                 linkSlowCase(iter);
    1736                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
    1737                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
    1738                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
    1739                 emitCTICall(Interpreter::cti_op_mul);
    1740                 emitPutVirtualRegister(dst);
    1741             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
    1742                 linkSlowCase(iter);
    1743                 linkSlowCase(iter);
    1744                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
    1745                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
    1746                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
    1747                 emitCTICall(Interpreter::cti_op_mul);
    1748                 emitPutVirtualRegister(dst);
    1749             } else
    1750                 compileBinaryArithOpSlowCase(op_mul, iter, dst, src1, src2, OperandTypes::fromInt(currentInstruction[4].u.operand));
     1507            compileFastArithSlow_op_mul(currentInstruction, iter);
    17511508            NEXT_OPCODE(op_mul);
    17521509        }
     
    19331690    Jump array_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
    19341691
    1935     add32(X86::eax, X86::eax);
    1936     add32(Imm32(1), X86::eax);
    1937    
     1692    // X86::eax contains a 64 bit value (is signed, is zero extended) so we don't need sign extend here.
     1693    emitFastArithIntToImmNoCheck(X86::eax);
     1694
    19381695    ret();
    19391696
     
    19511708    Jump string_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
    19521709
    1953     add32(X86::eax, X86::eax);
    1954     add32(Imm32(1), X86::eax);
     1710    // X86::eax contains a 64 bit value (is signed, is zero extended) so we don't need sign extend here.
     1711    emitFastArithIntToImmNoCheck(X86::eax);
    19551712   
    19561713    ret();
  • trunk/JavaScriptCore/jit/JIT.h

    r39440 r39540  
    389389        void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
    390390        void putDoubleResultToJSNumberCellOrJSImmediate(X86Assembler::XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86Assembler::XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2);
     391
     392        void compileFastArith_op_add(Instruction*);
     393        void compileFastArith_op_mul(Instruction*);
     394        void compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2);
     395        void compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2);
     396        void compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2);
     397        void compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2);
     398        void compileFastArith_op_pre_inc(unsigned srcDst);
     399        void compileFastArith_op_pre_dec(unsigned srcDst);
     400        void compileFastArith_op_post_inc(unsigned result, unsigned srcDst);
     401        void compileFastArith_op_post_dec(unsigned result, unsigned srcDst);
     402        void compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
     403        void compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
     404        void compileFastArithSlow_op_mod(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
     405        void compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
     406        void compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
     407        void compileFastArithSlow_op_rshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
     408        void compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
     409        void compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
     410        void compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
     411        void compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
    391412        void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
    392         void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
     413        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
    393414
    394415        void emitGetVirtualRegister(int src, RegisterID dst);
     
    413434
    414435        JSValue* getConstantImmediateNumericArg(unsigned src);
    415         unsigned getDeTaggedConstantImmediate(JSValue* imm);
     436        JSValue* getConstantOperand(unsigned src);
     437        int32_t getConstantOperandImmediateInt(unsigned src);
     438        bool isOperandConstantImmediateInt(unsigned src);
     439        bool isOperandConstant31BitImmediateInt(unsigned src);
    416440
    417441        Jump emitJumpIfJSCell(RegisterID);
     
    440464        Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
    441465        void emitFastArithReTagImmediate(RegisterID);
    442         void emitFastArithPotentiallyReTagImmediate(RegisterID);
    443466        void emitFastArithImmToInt(RegisterID);
    444         void emitFastArithIntToImmOrSlowCase(RegisterID);
    445467        void emitFastArithIntToImmNoCheck(RegisterID);
    446468
  • trunk/JavaScriptCore/jit/JITArithmetic.cpp

    r39316 r39540  
    4747namespace JSC {
    4848
     49void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2)
     50{
     51    emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
     52    // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmNums'? - we *probably* ought to be consistent.
     53    emitJumpSlowCaseIfNotImmNum(X86::eax);
     54    emitJumpSlowCaseIfNotImmNum(X86::ecx);
     55    emitFastArithImmToInt(X86::eax);
     56    emitFastArithImmToInt(X86::ecx);
     57#if !PLATFORM(X86)
     58    // Mask with 0x1f as per ecma-262 11.7.2 step 7.
     59    // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
     60    and32(Imm32(0x1f), X86::ecx);
     61#endif
     62    lshift32(X86::ecx, X86::eax);
     63#if USE(ALTERNATE_JSIMMEDIATE)
     64    emitFastArithIntToImmNoCheck(X86::eax);
     65#else
     66    addSlowCase(joAdd32(X86::eax, X86::eax));
     67    signExtend32ToPtr(X86::eax, X86::eax);
     68    emitFastArithReTagImmediate(X86::eax);
     69#endif
     70    emitPutVirtualRegister(result);
     71}
     72void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
     73{
     74#if USE(ALTERNATE_JSIMMEDIATE)
     75    UNUSED_PARAM(op1);
     76    UNUSED_PARAM(op2);
     77    linkSlowCase(iter);
     78    linkSlowCase(iter);
     79#else
     80    // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
     81    Jump notImm1 = getSlowCase(iter);
     82    Jump notImm2 = getSlowCase(iter);
     83    linkSlowCase(iter);
     84    emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
     85    notImm1.link(this);
     86    notImm2.link(this);
     87#endif
     88    emitPutJITStubArg(X86::eax, 1);
     89    emitPutJITStubArg(X86::ecx, 2);
     90    emitCTICall(Interpreter::cti_op_lshift);
     91    emitPutVirtualRegister(result);
     92}
     93
     94void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2)
     95{
     96    if (JSValue* value = getConstantImmediateNumericArg(op2)) {
     97        emitGetVirtualRegister(op1, X86::eax);
     98        emitJumpSlowCaseIfNotImmNum(X86::eax);
     99        // Mask with 0x1f as per ecma-262 11.7.2 step 7.
     100        rshiftPtr(Imm32(JSImmediate::getTruncatedUInt32(value) & 0x1f), X86::eax);
     101    } else {
     102        emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
     103        emitJumpSlowCaseIfNotImmNum(X86::eax);
     104        emitJumpSlowCaseIfNotImmNum(X86::ecx);
     105        emitFastArithImmToInt(X86::ecx);
     106#if !PLATFORM(X86)
     107        // Mask with 0x1f as per ecma-262 11.7.2 step 7.
     108        // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
     109        and32(Imm32(0x1f), X86::ecx);
     110#endif
     111        rshiftPtr(X86::ecx, X86::eax);
     112    }
     113    orPtr(Imm32(JSImmediate::TagBitTypeInteger), X86::eax);
     114    emitPutVirtualRegister(result);
     115}
     116void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
     117{
     118    linkSlowCase(iter);
     119    if (getConstantImmediateNumericArg(op2))
     120        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     121    else {
     122        linkSlowCase(iter);
     123        emitPutJITStubArg(X86::ecx, 2);
     124    }
     125
     126    emitPutJITStubArg(X86::eax, 1);
     127    emitCTICall(Interpreter::cti_op_rshift);
     128    emitPutVirtualRegister(result);
     129}
     130
     131void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2)
     132{
     133    if (isOperandConstant31BitImmediateInt(op1)) {
     134        emitGetVirtualRegister(op2, X86::eax);
     135        emitJumpSlowCaseIfNotImmNum(X86::eax);
     136        andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax);
     137    } else if (isOperandConstant31BitImmediateInt(op2)) {
     138        emitGetVirtualRegister(op1, X86::eax);
     139        emitJumpSlowCaseIfNotImmNum(X86::eax);
     140        andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax);
     141    } else {
     142        emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
     143        andPtr(X86::edx, X86::eax);
     144        emitJumpSlowCaseIfNotImmNum(X86::eax);
     145    }
     146    emitPutVirtualRegister(result);
     147}
     148void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
     149{
     150    linkSlowCase(iter);
     151    if (isOperandConstant31BitImmediateInt(op1)) {
     152        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     153        emitPutJITStubArg(X86::eax, 2);
     154    } else if (isOperandConstant31BitImmediateInt(op2)) {
     155        emitPutJITStubArg(X86::eax, 1);
     156        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     157    } else {
     158        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     159        emitPutJITStubArg(X86::edx, 2);
     160    }
     161    emitCTICall(Interpreter::cti_op_bitand);
     162    emitPutVirtualRegister(result);
     163}
     164
     165void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2)
     166{
     167    emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
     168    emitJumpSlowCaseIfNotImmNum(X86::eax);
     169    emitJumpSlowCaseIfNotImmNum(X86::ecx);
     170#if USE(ALTERNATE_JSIMMEDIATE)
     171    addSlowCase(jePtr(X86::ecx, ImmPtr(JSImmediate::zeroImmediate())));
     172    emitFastArithImmToInt(X86::eax);
     173    emitFastArithImmToInt(X86::ecx);
     174    mod32(X86::ecx, X86::eax, X86::edx);
     175    emitFastArithIntToImmNoCheck(X86::edx);
     176#else
     177    emitFastArithDeTagImmediate(X86::eax);
     178    addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
     179    mod32(X86::ecx, X86::eax, X86::edx);
     180    signExtend32ToPtr(X86::edx, X86::edx);
     181    emitFastArithReTagImmediate(X86::edx);
     182#endif
     183    move(X86::edx, X86::eax);
     184    emitPutVirtualRegister(result);
     185}
     186void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter)
     187{
     188#if USE(ALTERNATE_JSIMMEDIATE)
     189    linkSlowCase(iter);
     190    linkSlowCase(iter);
     191    linkSlowCase(iter);
     192#else
     193    Jump notImm1 = getSlowCase(iter);
     194    Jump notImm2 = getSlowCase(iter);
     195    linkSlowCase(iter);
     196    emitFastArithReTagImmediate(X86::eax);
     197    emitFastArithReTagImmediate(X86::ecx);
     198    notImm1.link(this);
     199    notImm2.link(this);
     200#endif
     201    emitPutJITStubArg(X86::eax, 1);
     202    emitPutJITStubArg(X86::ecx, 2);
     203    emitCTICall(Interpreter::cti_op_mod);
     204    emitPutVirtualRegister(result);
     205}
     206
     207void JIT::compileFastArith_op_add(Instruction* currentInstruction)
     208{
     209    unsigned result = currentInstruction[1].u.operand;
     210    unsigned op1 = currentInstruction[2].u.operand;
     211    unsigned op2 = currentInstruction[3].u.operand;
     212
     213    if (isOperandConstantImmediateInt(op1)) {
     214        emitGetVirtualRegister(op2, X86::eax);
     215        emitJumpSlowCaseIfNotImmNum(X86::eax);
     216#if USE(ALTERNATE_JSIMMEDIATE)
     217        // FIXME: investigate performing a 31-bit add here (can we preserve upper bit & detect overflow from low word to high?)
     218        //        (or, detect carry? - if const is positive, will only carry when overflowing from negative to positive?)
     219        emitFastArithImmToInt(X86::eax);
     220        addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax));
     221        emitFastArithIntToImmNoCheck(X86::eax);
     222#else
     223        addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax));
     224        signExtend32ToPtr(X86::eax, X86::eax);
     225#endif
     226        emitPutVirtualRegister(result);
     227    } else if (isOperandConstantImmediateInt(op2)) {
     228        emitGetVirtualRegister(op1, X86::eax);
     229        emitJumpSlowCaseIfNotImmNum(X86::eax);
     230#if USE(ALTERNATE_JSIMMEDIATE)
     231        emitFastArithImmToInt(X86::eax);
     232        addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax));
     233        emitFastArithIntToImmNoCheck(X86::eax);
     234#else
     235        addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax));
     236        signExtend32ToPtr(X86::eax, X86::eax);
     237#endif
     238        emitPutVirtualRegister(result);
     239    } else {
     240        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     241        if (types.first().mightBeNumber() && types.second().mightBeNumber())
     242            compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
     243        else {
     244            emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     245            emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     246            emitCTICall(Interpreter::cti_op_add);
     247            emitPutVirtualRegister(result);
     248        }
     249    }
     250}
     251void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     252{
     253    unsigned result = currentInstruction[1].u.operand;
     254    unsigned op1 = currentInstruction[2].u.operand;
     255    unsigned op2 = currentInstruction[3].u.operand;
     256
     257    if (isOperandConstantImmediateInt(op1)) {
     258#if USE(ALTERNATE_JSIMMEDIATE)
     259        linkSlowCase(iter);
     260        linkSlowCase(iter);
     261        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     262        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     263#else
     264        Jump notImm = getSlowCase(iter);
     265        linkSlowCase(iter);
     266        sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax);
     267        notImm.link(this);
     268        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     269        emitPutJITStubArg(X86::eax, 2);
     270#endif
     271        emitCTICall(Interpreter::cti_op_add);
     272        emitPutVirtualRegister(result);
     273    } else if (isOperandConstantImmediateInt(op2)) {
     274#if USE(ALTERNATE_JSIMMEDIATE)
     275        linkSlowCase(iter);
     276        linkSlowCase(iter);
     277        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     278        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     279#else
     280        Jump notImm = getSlowCase(iter);
     281        linkSlowCase(iter);
     282        sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax);
     283        notImm.link(this);
     284        emitPutJITStubArg(X86::eax, 1);
     285        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     286#endif
     287        emitCTICall(Interpreter::cti_op_add);
     288        emitPutVirtualRegister(result);
     289    } else {
     290        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     291        ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
     292        compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
     293    }
     294}
     295
     296void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
     297{
     298    unsigned result = currentInstruction[1].u.operand;
     299    unsigned op1 = currentInstruction[2].u.operand;
     300    unsigned op2 = currentInstruction[3].u.operand;
     301
     302    // For now, only plant a fast int case if the constant operand is greater than zero.
     303    int32_t value;
     304    if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
     305        emitGetVirtualRegister(op2, X86::eax);
     306        emitJumpSlowCaseIfNotImmNum(X86::eax);
     307#if USE(ALTERNATE_JSIMMEDIATE)
     308        emitFastArithImmToInt(X86::eax);
     309        addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
     310        emitFastArithIntToImmNoCheck(X86::eax);
     311#else
     312        emitFastArithDeTagImmediate(X86::eax);
     313        addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
     314        signExtend32ToPtr(X86::eax, X86::eax);
     315        emitFastArithReTagImmediate(X86::eax);
     316#endif
     317        emitPutVirtualRegister(result);
     318    } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
     319        emitGetVirtualRegister(op1, X86::eax);
     320        emitJumpSlowCaseIfNotImmNum(X86::eax);
     321#if USE(ALTERNATE_JSIMMEDIATE)
     322        emitFastArithImmToInt(X86::eax);
     323        addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
     324        emitFastArithIntToImmNoCheck(X86::eax);
     325#else
     326        emitFastArithDeTagImmediate(X86::eax);
     327        addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
     328        signExtend32ToPtr(X86::eax, X86::eax);
     329        emitFastArithReTagImmediate(X86::eax);
     330#endif
     331        emitPutVirtualRegister(result);
     332    } else
     333        compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
     334}
     335void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     336{
     337    int result = currentInstruction[1].u.operand;
     338    int op1 = currentInstruction[2].u.operand;
     339    int op2 = currentInstruction[3].u.operand;
     340
     341    if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
     342        || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
     343        linkSlowCase(iter);
     344        linkSlowCase(iter);
     345        // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
     346        emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
     347        emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
     348        emitCTICall(Interpreter::cti_op_mul);
     349        emitPutVirtualRegister(result);
     350    } else
     351        compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
     352}
     353
     354void JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst)
     355{
     356    emitGetVirtualRegister(srcDst, X86::eax);
     357    move(X86::eax, X86::edx);
     358    emitJumpSlowCaseIfNotImmNum(X86::eax);
     359#if USE(ALTERNATE_JSIMMEDIATE)
     360    emitFastArithImmToInt(X86::edx);
     361    addSlowCase(joAdd32(Imm32(1), X86::edx));
     362    emitFastArithIntToImmNoCheck(X86::edx);
     363#else
     364    addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
     365    signExtend32ToPtr(X86::edx, X86::edx);
     366#endif
     367    emitPutVirtualRegister(srcDst, X86::edx);
     368    emitPutVirtualRegister(result);
     369}
     370void JIT::compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
     371{
     372    linkSlowCase(iter);
     373    linkSlowCase(iter);
     374    emitPutJITStubArg(X86::eax, 1);
     375    emitCTICall(Interpreter::cti_op_post_inc);
     376    emitPutVirtualRegister(srcDst, X86::edx);
     377    emitPutVirtualRegister(result);
     378}
     379
     380void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst)
     381{
     382    emitGetVirtualRegister(srcDst, X86::eax);
     383    move(X86::eax, X86::edx);
     384    emitJumpSlowCaseIfNotImmNum(X86::eax);
     385#if USE(ALTERNATE_JSIMMEDIATE)
     386    emitFastArithImmToInt(X86::edx);
     387    addSlowCase(joSub32(Imm32(1), X86::edx));
     388    emitFastArithIntToImmNoCheck(X86::edx);
     389#else
     390    addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
     391    signExtend32ToPtr(X86::edx, X86::edx);
     392#endif
     393    emitPutVirtualRegister(srcDst, X86::edx);
     394    emitPutVirtualRegister(result);
     395}
     396void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
     397{
     398    linkSlowCase(iter);
     399    linkSlowCase(iter);
     400    emitPutJITStubArg(X86::eax, 1);
     401    emitCTICall(Interpreter::cti_op_post_dec);
     402    emitPutVirtualRegister(srcDst, X86::edx);
     403    emitPutVirtualRegister(result);
     404}
     405
     406void JIT::compileFastArith_op_pre_inc(unsigned srcDst)
     407{
     408    emitGetVirtualRegister(srcDst, X86::eax);
     409    emitJumpSlowCaseIfNotImmNum(X86::eax);
     410#if USE(ALTERNATE_JSIMMEDIATE)
     411    emitFastArithImmToInt(X86::eax);
     412    // FIXME: Could add ptr & specify int64; no need to re-sign-extend?
     413    addSlowCase(joAdd32(Imm32(1), X86::eax));
     414    emitFastArithIntToImmNoCheck(X86::eax);
     415#else
     416    addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
     417    signExtend32ToPtr(X86::eax, X86::eax);
     418#endif
     419    emitPutVirtualRegister(srcDst);
     420}
     421void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
     422{
     423    Jump notImm = getSlowCase(iter);
     424    linkSlowCase(iter);
     425    emitGetVirtualRegister(srcDst, X86::eax);
     426    notImm.link(this);
     427    emitPutJITStubArg(X86::eax, 1);
     428    emitCTICall(Interpreter::cti_op_pre_inc);
     429    emitPutVirtualRegister(srcDst);
     430}
     431
     432void JIT::compileFastArith_op_pre_dec(unsigned srcDst)
     433{
     434    emitGetVirtualRegister(srcDst, X86::eax);
     435    emitJumpSlowCaseIfNotImmNum(X86::eax);
     436#if USE(ALTERNATE_JSIMMEDIATE)
     437    emitFastArithImmToInt(X86::eax);
     438    addSlowCase(joSub32(Imm32(1), X86::eax));
     439    emitFastArithIntToImmNoCheck(X86::eax);
     440#else
     441    addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
     442    signExtend32ToPtr(X86::eax, X86::eax);
     443#endif
     444    emitPutVirtualRegister(srcDst);
     445}
     446void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
     447{
     448    Jump notImm = getSlowCase(iter);
     449    linkSlowCase(iter);
     450    emitGetVirtualRegister(srcDst, X86::eax);
     451    notImm.link(this);
     452    emitPutJITStubArg(X86::eax, 1);
     453    emitCTICall(Interpreter::cti_op_pre_dec);
     454    emitPutVirtualRegister(srcDst);
     455}
     456
     457
    49458#if !ENABLE(JIT_OPTIMIZE_ARITHMETIC)
    50459
     
    270679        __ subl_rr(X86::edx, X86::eax);
    271680        addSlowCase(__ jo());
     681        signExtend32ToPtr(X86::eax, X86::eax);
    272682        emitFastArithReTagImmediate(X86::eax);
    273683    } else {
     
    288698        __ imull_rr(X86::edx, X86::eax);
    289699        addSlowCase(__ jo());
     700        signExtend32ToPtr(X86::eax, X86::eax);
    290701        emitFastArithReTagImmediate(X86::eax);
    291702    }
  • trunk/JavaScriptCore/jit/JITInlineMethods.h

    r39428 r39540  
    4242namespace JSC {
    4343
    44 static ALWAYS_INLINE uintptr_t asInteger(JSValue* value)
    45 {
    46     return reinterpret_cast<uintptr_t>(value);
    47 }
    48 
    4944ALWAYS_INLINE void JIT::killLastResultRegister()
    5045{
     
    127122}
    128123
     124ALWAYS_INLINE JSValue* JIT::getConstantOperand(unsigned src)
     125{
     126    ASSERT(m_codeBlock->isConstantRegisterIndex(src));
     127    return m_codeBlock->getConstant(src);
     128}
     129
     130ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src)
     131{
     132    return static_cast<int32_t>(JSImmediate::intValue(getConstantOperand(src)));
     133}
     134
     135ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
     136{
     137    return m_codeBlock->isConstantRegisterIndex(src) && JSImmediate::isNumber(getConstantOperand(src));
     138}
     139
     140ALWAYS_INLINE bool JIT::isOperandConstant31BitImmediateInt(unsigned src)
     141{
     142    if (!m_codeBlock->isConstantRegisterIndex(src))
     143        return false;
     144
     145    JSValue* value = getConstantOperand(src);
     146
     147#if USE(ALTERNATE_JSIMMEDIATE)
     148    if (!JSImmediate::isNumber(value))
     149        return false;
     150
     151    int32_t imm = JSImmediate::intValue(value);
     152    return (imm == ((imm << 1) >> 1));
     153#else
     154    return JSImmediate::isNumber(value);
     155#endif
     156}
     157
    129158// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
    130159ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
     
    304333}
    305334
    306 ALWAYS_INLINE unsigned JIT::getDeTaggedConstantImmediate(JSValue* imm)
    307 {
    308     ASSERT(JSImmediate::isNumber(imm));
    309     return asInteger(imm) & ~JSImmediate::TagBitTypeInteger;
    310 }
    311 
    312335ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
    313336{
    314     sub32(Imm32(JSImmediate::TagBitTypeInteger), reg);
     337    subPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
    315338}
    316339
    317340ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
    318341{
    319     return jzSub32(Imm32(JSImmediate::TagBitTypeInteger), reg);
     342    return jzSubPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
    320343}
    321344
    322345ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID reg)
    323346{
    324     add32(Imm32(JSImmediate::TagBitTypeInteger), reg);
     347    addPtr(Imm32(JSImmediate::TagBitTypeInteger), reg);
     348}
     349
     350ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
     351{
     352    rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
     353}
     354
     355ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID reg)
     356{
    325357    signExtend32ToPtr(reg, reg);
    326 }
    327 
    328 ALWAYS_INLINE void JIT::emitFastArithPotentiallyReTagImmediate(RegisterID reg)
    329 {
    330     or32(Imm32(JSImmediate::TagBitTypeInteger), reg);
    331     signExtend32ToPtr(reg, reg);
    332 }
    333 
    334 ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
    335 {
    336     rshift32(Imm32(JSImmediate::IntegerPayloadShift), reg);
    337 }
    338 
    339 ALWAYS_INLINE void JIT::emitFastArithIntToImmOrSlowCase(RegisterID reg)
    340 {
    341     addSlowCase(joAdd32(reg, reg));
    342     emitFastArithReTagImmediate(reg);
    343 }
    344 
    345 ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID reg)
    346 {
    347     add32(reg, reg);
     358    addPtr(reg, reg);
    348359    emitFastArithReTagImmediate(reg);
    349360}
Note: See TracChangeset for help on using the changeset viewer.