Changeset 192600 in webkit


Ignore:
Timestamp:
Nov 18, 2015 4:54:37 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

Snippefy op_mul for the baseline JIT.
https://bugs.webkit.org/show_bug.cgi?id=151393

Reviewed by Geoffrey Garen.

Benchmarks shows that perf is neutral on x86 and x86_64 with the DFG enabled.

With the DFG disabled (relying on the baseline JIT for perf), LongSpider
3d-morph shows a 7.6% regression. However, there are other benchmarks that shows
a progression e.g. on Kraken, audio-beat-detection and audio-fft.

Upon inspection of the generated code for 3d-morph, the only differences is the
added use of a scratch register for the result as well as a jump around the
code that handles double types. It does not look like we're generating bad code.
I'll consider the perf acceptable in aggregate.

  • bytecode/PolymorphicAccess.cpp:

(JSC::AccessCase::generate):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::boxInt32):

  • jit/IntrinsicEmitter.cpp:

(JSC::AccessCase::emitIntrinsicGetter):

  • Changed AssemblyHelpers::boxInt32() to take a TagRegistersMode. The pre-existing boxInt32() always assume that the tag registers are not available. Since we should assume we have tag registers by default, I also changed all the other clients to explicitly specify a more of DoNotHaveTagRegisters. That is except for the snippet generators that do have the tag registers.
  • jit/JIT.h:
  • jit/JITArithmetic.cpp:

(JSC::JIT::compileBinaryArithOpSlowCase):
(JSC::JIT::emit_op_div):
(JSC::JIT::emitSlow_op_add):
(JSC::JIT::emit_op_mul):
(JSC::JIT::emitSlow_op_mul):
(JSC::JIT::emit_op_sub):
(JSC::JIT::compileBinaryArithOp): Deleted.

  • jit/JITArithmetic32_64.cpp:

(JSC::JIT::emitBinaryDoubleOp):
(JSC::JIT::emit_op_div):
(JSC::JIT::emit_op_mul): Deleted.
(JSC::JIT::emitSlow_op_mul): Deleted.

  • jit/JITMulGenerator.cpp: Added.

(JSC::JITMulGenerator::generateFastPath):

  • jit/JITMulGenerator.h: Added.

(JSC::JITMulGenerator::JITMulGenerator):
(JSC::JITMulGenerator::didEmitFastPath):
(JSC::JITMulGenerator::endJumpList):
(JSC::JITMulGenerator::slowPathJumpList):

  • tests/stress/op_mul.js: Added.

(o1.valueOf):
(generateScenarios):
(printScenarios):
(testCases.func):
(func):
(initializeTestCases):
(stringifyIfNeeded):
(isIdentical):
(runTest):

  • Tests that JIT op_mul results are equivalent to the expected values as defined by the LLINT.
Location:
trunk/Source/JavaScriptCore
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r192321 r192600  
    446446    jit/JITExceptions.cpp
    447447    jit/JITInlineCacheGenerator.cpp
     448    jit/JITMulGenerator.cpp
    448449    jit/JITOpcodes.cpp
    449450    jit/JITOpcodes32_64.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r192599 r192600  
     12015-11-18  Mark Lam  <mark.lam@apple.com>
     2
     3        Snippefy op_mul for the baseline JIT.
     4        https://bugs.webkit.org/show_bug.cgi?id=151393
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Benchmarks shows that perf is neutral on x86 and x86_64 with the DFG enabled.
     9
     10        With the DFG disabled (relying on the baseline JIT for perf), LongSpider
     11        3d-morph shows a 7.6% regression.  However, there are other benchmarks that shows
     12        a progression e.g. on Kraken, audio-beat-detection and audio-fft.
     13
     14        Upon inspection of the generated code for 3d-morph, the only differences is the
     15        added use of a scratch register for the result as well as a jump around the
     16        code that handles double types.  It does not look like we're generating bad code.
     17        I'll consider the perf acceptable in aggregate.
     18
     19        * CMakeLists.txt:
     20        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     21        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     22        * JavaScriptCore.xcodeproj/project.pbxproj:
     23
     24        * bytecode/PolymorphicAccess.cpp:
     25        (JSC::AccessCase::generate):
     26        * jit/AssemblyHelpers.h:
     27        (JSC::AssemblyHelpers::boxInt32):
     28        * jit/IntrinsicEmitter.cpp:
     29        (JSC::AccessCase::emitIntrinsicGetter):
     30        - Changed AssemblyHelpers::boxInt32() to take a TagRegistersMode.
     31          The pre-existing boxInt32() always assume that the tag registers are not
     32          available.  Since we should assume we have tag registers by default, I also
     33          changed all the other clients to explicitly specify a more of
     34          DoNotHaveTagRegisters.  That is except for the snippet generators that do have
     35          the tag registers.
     36
     37        * jit/JIT.h:
     38        * jit/JITArithmetic.cpp:
     39        (JSC::JIT::compileBinaryArithOpSlowCase):
     40        (JSC::JIT::emit_op_div):
     41        (JSC::JIT::emitSlow_op_add):
     42        (JSC::JIT::emit_op_mul):
     43        (JSC::JIT::emitSlow_op_mul):
     44        (JSC::JIT::emit_op_sub):
     45        (JSC::JIT::compileBinaryArithOp): Deleted.
     46        * jit/JITArithmetic32_64.cpp:
     47        (JSC::JIT::emitBinaryDoubleOp):
     48        (JSC::JIT::emit_op_div):
     49        (JSC::JIT::emit_op_mul): Deleted.
     50        (JSC::JIT::emitSlow_op_mul): Deleted.
     51        * jit/JITMulGenerator.cpp: Added.
     52        (JSC::JITMulGenerator::generateFastPath):
     53        * jit/JITMulGenerator.h: Added.
     54        (JSC::JITMulGenerator::JITMulGenerator):
     55        (JSC::JITMulGenerator::didEmitFastPath):
     56        (JSC::JITMulGenerator::endJumpList):
     57        (JSC::JITMulGenerator::slowPathJumpList):
     58
     59        * tests/stress/op_mul.js: Added.
     60        (o1.valueOf):
     61        (generateScenarios):
     62        (printScenarios):
     63        (testCases.func):
     64        (func):
     65        (initializeTestCases):
     66        (stringifyIfNeeded):
     67        (isIdentical):
     68        (runTest):
     69        - Tests that JIT op_mul results are equivalent to the expected values as
     70          defined by the LLINT.
     71
    1722015-11-18  Mark Lam  <mark.lam@apple.com>
    273
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r192353 r192600  
    650650    <ClCompile Include="..\jit\JITExceptions.cpp" />
    651651    <ClCompile Include="..\jit\JITInlineCacheGenerator.cpp" />
     652    <ClCompile Include="..\jit\JITMulGenerator.cpp" />
    652653    <ClCompile Include="..\jit\JITOpcodes.cpp" />
    653654    <ClCompile Include="..\jit\JITOpcodes32_64.cpp" />
     
    14681469    <ClInclude Include="..\jit\JITInlineCacheGenerator.h" />
    14691470    <ClInclude Include="..\jit\JITInlines.h" />
     1471    <ClInclude Include="..\jit\JITMulGenerator.h" />
    14701472    <ClInclude Include="..\jit\JITOperations.h" />
    14711473    <ClInclude Include="..\jit\JITStubRoutine.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r192353 r192600  
    445445      <Filter>jit</Filter>
    446446    </ClCompile>
     447    <ClCompile Include="..\jit\JITMulGenerator.cpp">
     448      <Filter>jit</Filter>
     449    </ClCompile>
    447450    <ClCompile Include="..\jit\JITOpcodes.cpp">
    448451      <Filter>jit</Filter>
     
    25182521    </ClInclude>
    25192522    <ClInclude Include="..\jit\JITInlines.h">
     2523      <Filter>jit</Filter>
     2524    </ClInclude>
     2525    <ClInclude Include="..\jit\JITMulGenerator.h">
    25202526      <Filter>jit</Filter>
    25212527    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r192591 r192600  
    19631963                FE1220271BE7F58C0039E6F2 /* JITAddGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */; };
    19641964                FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */; };
     1965                FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */; settings = {ASSET_TAGS = (); }; };
     1966                FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */; settings = {ASSET_TAGS = (); }; };
    19651967                FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; };
    19661968                FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1C0FFE1B194FD100B53FCA /* Exception.cpp */; };
     
    40934095                FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITAddGenerator.cpp; sourceTree = "<group>"; };
    40944096                FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITAddGenerator.h; sourceTree = "<group>"; };
     4097                FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITMulGenerator.cpp; sourceTree = "<group>"; };
     4098                FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMulGenerator.h; sourceTree = "<group>"; };
    40954099                FE1C0FFC1B193E9800B53FCA /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
    40964100                FE1C0FFE1B194FD100B53FCA /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = "<group>"; };
     
    47754779                                0FB14E1D18124ACE009B6B4D /* JITInlineCacheGenerator.h */,
    47764780                                86CC85A00EE79A4700288682 /* JITInlines.h */,
     4781                                FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */,
     4782                                FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */,
    47774783                                BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */,
    47784784                                A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */,
     
    74187424                                BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
    74197425                                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
     7426                                FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */,
    74207427                                86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */,
    74217428                                0F431738146BAC69007E3890 /* ListableHandler.h in Headers */,
     
    89628969                                FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */,
    89638970                                7B0247561B8682E100542440 /* WASMFunctionParser.cpp in Sources */,
     8971                                FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */,
    89648972                                7B39F76D1B62DE2E00360FB4 /* WASMModuleParser.cpp in Sources */,
    89658973                                7B39F7721B63574D00360FB4 /* WASMReader.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp

    r191594 r192600  
    10591059        state.failAndIgnore.append(
    10601060            jit.branch32(CCallHelpers::LessThan, scratchGPR, CCallHelpers::TrustedImm32(0)));
    1061         jit.boxInt32(scratchGPR, valueRegs);
     1061        jit.boxInt32(scratchGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters);
    10621062        state.succeed();
    10631063        return;
     
    10661066    case StringLength: {
    10671067        jit.load32(CCallHelpers::Address(baseGPR, JSString::offsetOfLength()), valueRegs.payloadGPR());
    1068         jit.boxInt32(valueRegs.payloadGPR(), valueRegs);
     1068        jit.boxInt32(valueRegs.payloadGPR(), valueRegs, CCallHelpers::DoNotHaveTagRegisters);
    10691069        state.succeed();
    10701070        return;
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r192531 r192600  
    11131113    }
    11141114
    1115     void boxInt32(GPRReg intGPR, JSValueRegs boxedRegs)
    1116     {
    1117 #if USE(JSVALUE64)
    1118         move(intGPR, boxedRegs.gpr());
    1119         or64(TrustedImm64(TagTypeNumber), boxedRegs.gpr());
    1120 #else
     1115    void boxInt32(GPRReg intGPR, JSValueRegs boxedRegs, TagRegistersMode mode = HaveTagRegisters)
     1116    {
     1117#if USE(JSVALUE64)
     1118        if (mode == DoNotHaveTagRegisters) {
     1119            move(intGPR, boxedRegs.gpr());
     1120            or64(TrustedImm64(TagTypeNumber), boxedRegs.gpr());
     1121        } else
     1122            or64(GPRInfo::tagTypeNumberRegister, intGPR, boxedRegs.gpr());
     1123#else
     1124        UNUSED_PARAM(mode);
    11211125        move(intGPR, boxedRegs.payloadGPR());
    11221126        move(TrustedImm32(JSValue::Int32Tag), boxedRegs.tagGPR());
  • trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp

    r191220 r192600  
    7878    case TypedArrayLengthIntrinsic: {
    7979        jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
    80         jit.boxInt32(valueGPR, valueRegs);
     80        jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters);
    8181        state.succeed();
    8282        return;
     
    9393        }
    9494
    95         jit.boxInt32(valueGPR, valueRegs);
     95        jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters);
    9696        state.succeed();
    9797        return;
     
    119119        done.link(&jit);
    120120       
    121         jit.boxInt32(valueGPR, valueRegs);
     121        jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters);
    122122        state.succeed();
    123123        return;
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r192155 r192600  
    463463
    464464        void emitTagBool(RegisterID);
    465         void compileBinaryArithOp(OpcodeID, int dst, int src1, int src2, OperandTypes opi);
    466465        void compileBinaryArithOpSlowCase(Instruction*, OpcodeID, Vector<SlowCaseEntry>::iterator&, int dst, int src1, int src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
    467466
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r192599 r192600  
    3232#include "JITAddGenerator.h"
    3333#include "JITInlines.h"
     34#include "JITMulGenerator.h"
    3435#include "JITOperations.h"
    3536#include "JITSubGenerator.h"
     
    663664/* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
    664665
    665 void JIT::compileBinaryArithOp(OpcodeID opcodeID, int, int op1, int op2, OperandTypes)
    666 {
    667     emitGetVirtualRegisters(op1, regT0, op2, regT1);
    668     emitJumpSlowCaseIfNotInt(regT0);
    669     emitJumpSlowCaseIfNotInt(regT1);
    670     ASSERT_UNUSED(opcodeID, opcodeID == op_mul);
    671     if (shouldEmitProfiling()) {
    672         // We want to be able to measure if this is taking the slow case just
    673         // because of negative zero. If this produces positive zero, then we
    674         // don't want the slow case to be taken because that will throw off
    675         // speculative compilation.
    676         move(regT0, regT2);
    677         addSlowCase(branchMul32(Overflow, regT1, regT2));
    678         JumpList done;
    679         done.append(branchTest32(NonZero, regT2));
    680         Jump negativeZero = branch32(LessThan, regT0, TrustedImm32(0));
    681         done.append(branch32(GreaterThanOrEqual, regT1, TrustedImm32(0)));
    682         negativeZero.link(this);
    683         // We only get here if we have a genuine negative zero. Record this,
    684         // so that the speculative JIT knows that we failed speculation
    685         // because of a negative zero.
    686         add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
    687         addSlowCase(jump());
    688         done.link(this);
    689         move(regT2, regT0);
    690     } else {
    691         addSlowCase(branchMul32(Overflow, regT1, regT0));
    692         addSlowCase(branchTest32(Zero, regT0));
    693     }
    694     emitTagInt(regT0, regT0);
    695 }
    696 
    697666void JIT::compileBinaryArithOpSlowCase(Instruction* currentInstruction, OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, int result, int op1, int op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
    698667{
     
    712681
    713682    linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
    714     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
    715         linkSlowCase(iter);
    716683
    717684    Label stubFunctionCall(this);
     
    761728    }
    762729
    763     if (opcodeID == op_mul)
    764         mulDouble(fpRegT2, fpRegT1);
    765     else {
    766         ASSERT(opcodeID == op_div);
    767         divDouble(fpRegT2, fpRegT1);
    768     }
     730    ASSERT_UNUSED(opcodeID, opcodeID == op_div);
     731    divDouble(fpRegT2, fpRegT1);
     732
    769733    moveDoubleTo64(fpRegT1, regT0);
    770734    sub64(tagTypeNumberRegister, regT0);
     
    772736
    773737    end.link(this);
    774 }
    775 
    776 void JIT::emit_op_mul(Instruction* currentInstruction)
    777 {
    778     int result = currentInstruction[1].u.operand;
    779     int op1 = currentInstruction[2].u.operand;
    780     int op2 = currentInstruction[3].u.operand;
    781     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    782 
    783     // For now, only plant a fast int case if the constant operand is greater than zero.
    784     int32_t value;
    785     if (isOperandConstantInt(op1) && ((value = getOperandConstantInt(op1)) > 0)) {
    786         emitGetVirtualRegister(op2, regT0);
    787         emitJumpSlowCaseIfNotInt(regT0);
    788         addSlowCase(branchMul32(Overflow, regT0, Imm32(value), regT1));
    789         emitTagInt(regT1, regT0);
    790     } else if (isOperandConstantInt(op2) && ((value = getOperandConstantInt(op2)) > 0)) {
    791         emitGetVirtualRegister(op1, regT0);
    792         emitJumpSlowCaseIfNotInt(regT0);
    793         addSlowCase(branchMul32(Overflow, regT0, Imm32(value), regT1));
    794         emitTagInt(regT1, regT0);
    795     } else
    796         compileBinaryArithOp(op_mul, result, op1, op2, types);
    797 
    798     emitPutVirtualRegister(result);
    799 }
    800 
    801 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    802 {
    803     int result = currentInstruction[1].u.operand;
    804     int op1 = currentInstruction[2].u.operand;
    805     int op2 = currentInstruction[3].u.operand;
    806     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    807 
    808     bool op1HasImmediateIntFastCase = isOperandConstantInt(op1) && getOperandConstantInt(op1) > 0;
    809     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantInt(op2) && getOperandConstantInt(op2) > 0;
    810     compileBinaryArithOpSlowCase(currentInstruction, op_mul, iter, result, op1, op2, types, op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
    811738}
    812739
     
    980907}
    981908
    982 void JIT::emit_op_sub(Instruction* currentInstruction)
     909void JIT::emit_op_mul(Instruction* currentInstruction)
    983910{
    984911    int result = currentInstruction[1].u.operand;
     
    1001928#endif
    1002929
     930    bool leftIsConstInt32 = isOperandConstantInt(op1);
     931    bool rightIsConstInt32 = isOperandConstantInt(op2);
     932    ResultType leftType = types.first();
     933    ResultType rightType = types.second();
     934    int32_t leftConstInt32 = 0;
     935    int32_t rightConstInt32 = 0;
     936
     937    uint32_t* profilingCounter = nullptr;
     938    if (shouldEmitProfiling())
     939        profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter;
     940
     941    ASSERT(!leftIsConstInt32 || !rightIsConstInt32);
     942
     943    if (leftIsConstInt32)
     944        leftConstInt32 = getOperandConstantInt(op1);
     945    if (rightIsConstInt32)
     946        rightConstInt32 = getOperandConstantInt(op2);
     947
     948    bool leftIsPositiveConstInt32 = leftIsConstInt32 && (leftConstInt32 > 0);
     949    bool rightIsPositiveConstInt32 = rightIsConstInt32 && (rightConstInt32 > 0);
     950
     951    if (leftIsPositiveConstInt32)
     952        emitGetVirtualRegister(op2, rightRegs);
     953    else if (rightIsPositiveConstInt32)
     954        emitGetVirtualRegister(op1, leftRegs);
     955    else {
     956        emitGetVirtualRegister(op1, leftRegs);
     957        emitGetVirtualRegister(op2, rightRegs);
     958    }
     959
     960    JITMulGenerator gen(resultRegs, leftRegs, rightRegs, leftType, rightType,
     961        leftIsPositiveConstInt32, rightIsPositiveConstInt32, leftConstInt32, rightConstInt32,
     962        fpRegT0, fpRegT1, scratchGPR, scratchFPR, profilingCounter);
     963
     964    gen.generateFastPath(*this);
     965
     966    if (gen.didEmitFastPath()) {
     967        gen.endJumpList().link(this);
     968        emitPutVirtualRegister(result, resultRegs);
     969
     970        addSlowCase(gen.slowPathJumpList());
     971    } else {
     972        ASSERT(gen.endJumpList().empty());
     973        ASSERT(gen.slowPathJumpList().empty());
     974        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
     975        slowPathCall.call();
     976    }
     977}
     978
     979void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     980{
     981    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
     982   
     983    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
     984    slowPathCall.call();
     985}
     986
     987void JIT::emit_op_sub(Instruction* currentInstruction)
     988{
     989    int result = currentInstruction[1].u.operand;
     990    int op1 = currentInstruction[2].u.operand;
     991    int op2 = currentInstruction[3].u.operand;
     992    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     993
     994#if USE(JSVALUE64)
     995    JSValueRegs leftRegs = JSValueRegs(regT0);
     996    JSValueRegs rightRegs = JSValueRegs(regT1);
     997    JSValueRegs resultRegs = leftRegs;
     998    GPRReg scratchGPR = regT2;
     999    FPRReg scratchFPR = InvalidFPRReg;
     1000#else
     1001    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
     1002    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
     1003    JSValueRegs resultRegs = leftRegs;
     1004    GPRReg scratchGPR = regT4;
     1005    FPRReg scratchFPR = fpRegT2;
     1006#endif
     1007
    10031008    emitGetVirtualRegister(op1, leftRegs);
    10041009    emitGetVirtualRegister(op2, rightRegs);
  • trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp

    r192295 r192600  
    513513        doTheMath.link(this);
    514514        switch (opcodeID) {
    515             case op_mul:
    516                 emitLoadDouble(op1, fpRegT2);
    517                 mulDouble(fpRegT2, fpRegT0);
    518                 emitStoreDouble(dst, fpRegT0);
    519                 break;
    520515            case op_div: {
    521516                emitLoadDouble(op1, fpRegT1);
     
    604599        // Do the math.
    605600        switch (opcodeID) {
    606             case op_mul:
    607                 emitLoadDouble(op2, fpRegT2);
    608                 mulDouble(fpRegT2, fpRegT0);
    609                 emitStoreDouble(dst, fpRegT0);
    610                 break;
    611601            case op_div: {
    612602                emitLoadDouble(op2, fpRegT2);
     
    677667}
    678668
    679 // Multiplication (*)
    680 
    681 void JIT::emit_op_mul(Instruction* currentInstruction)
    682 {
    683     int dst = currentInstruction[1].u.operand;
    684     int op1 = currentInstruction[2].u.operand;
    685     int op2 = currentInstruction[3].u.operand;
    686     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    687 
    688     m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
    689 
    690     JumpList notInt32Op1;
    691     JumpList notInt32Op2;
    692 
    693     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
    694     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
    695     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    696 
    697     // Int32 case.
    698     move(regT0, regT3);
    699     addSlowCase(branchMul32(Overflow, regT2, regT0));
    700     addSlowCase(branchTest32(Zero, regT0));
    701     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
    702 
    703     if (!supportsFloatingPoint()) {
    704         addSlowCase(notInt32Op1);
    705         addSlowCase(notInt32Op2);
    706         return;
    707     }
    708     Jump end = jump();
    709 
    710     // Double case.
    711     emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2);
    712     end.link(this);
    713 }
    714 
    715 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    716 {
    717     int dst = currentInstruction[1].u.operand;
    718     int op1 = currentInstruction[2].u.operand;
    719     int op2 = currentInstruction[3].u.operand;
    720     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    721 
    722     Jump overflow = getSlowCase(iter); // overflow check
    723     linkSlowCase(iter); // zero result check
    724 
    725     Jump negZero = branchOr32(Signed, regT2, regT3);
    726     emitStoreInt32(dst, TrustedImm32(0), (op1 == dst || op2 == dst));
    727 
    728     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
    729 
    730     negZero.link(this);
    731     // We only get here if we have a genuine negative zero. Record this,
    732     // so that the speculative JIT knows that we failed speculation
    733     // because of a negative zero.
    734     add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
    735     overflow.link(this);
    736 
    737     if (!supportsFloatingPoint()) {
    738         linkSlowCase(iter); // int32 check
    739         linkSlowCase(iter); // int32 check
    740     }
    741 
    742     if (supportsFloatingPoint()) {
    743         if (!types.first().definitelyIsNumber())
    744             linkSlowCase(iter); // double check
    745 
    746         if (!types.second().definitelyIsNumber()) {
    747             linkSlowCase(iter); // int32 check
    748             linkSlowCase(iter); // double check
    749         }
    750     }
    751 
    752     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
    753     slowPathCall.call();
    754 }
    755 
    756669// Division (/)
    757670
Note: See TracChangeset for help on using the changeset viewer.