Changeset 192836 in webkit


Ignore:
Timestamp:
Nov 30, 2015 3:13:41 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

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

Reviewed by Geoffrey Garen.

  • jit/JIT.h:
  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_op_div):
(JSC::JIT::emitSlow_op_div):
(JSC::JIT::compileBinaryArithOpSlowCase): Deleted.

  • jit/JITArithmetic32_64.cpp:

(JSC::JIT::emitBinaryDoubleOp):
(JSC::JIT::emit_op_div): Deleted.
(JSC::JIT::emitSlow_op_div): Deleted.

  • Removed the 32-bit specific op_div implementation. The 64-bit version with the op_div snippet can now service both 32-bit and 64-bit.


  • jit/JITDivGenerator.cpp: Added.

(JSC::JITDivGenerator::loadOperand):
(JSC::JITDivGenerator::generateFastPath):

  • jit/JITDivGenerator.h: Added.

(JSC::JITDivGenerator::JITDivGenerator):
(JSC::JITDivGenerator::didEmitFastPath):
(JSC::JITDivGenerator::endJumpList):
(JSC::JITDivGenerator::slowPathJumpList):

  • jit/JITInlines.h:

(JSC::JIT::getOperandConstantDouble): Added.

  • jit/SnippetOperand.h: Added.

(JSC::SnippetOperand::SnippetOperand):
(JSC::SnippetOperand::mightBeNumber):
(JSC::SnippetOperand::definitelyIsNumber):
(JSC::SnippetOperand::isConst):
(JSC::SnippetOperand::isConstInt32):
(JSC::SnippetOperand::isConstDouble):
(JSC::SnippetOperand::asRawBits):
(JSC::SnippetOperand::asConstInt32):
(JSC::SnippetOperand::asConstDouble):
(JSC::SnippetOperand::setConstInt32):
(JSC::SnippetOperand::setConstDouble):

  • The SnippetOperand encapsulates operand constness, const type, and profiling information. As a result:
    1. The argument list to the JITDivGenerator constructor is now more concise.
    2. The logic of the JITDivGenerator is now less verbose and easier to express.
  • parser/ResultType.h:

(JSC::ResultType::isInt32):
(JSC::ResultType::definitelyIsNumber):
(JSC::ResultType::definitelyIsString):
(JSC::ResultType::definitelyIsBoolean):
(JSC::ResultType::mightBeNumber):
(JSC::ResultType::isNotNumber):

  • Made these functions const because they were always meant to be const. This also allows me to enforce constness in the SnippetOperand.
Location:
trunk/Source/JavaScriptCore
Files:
3 added
10 edited

Legend:

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

    r192816 r192836  
    456456    jit/JITCode.cpp
    457457    jit/JITDisassembler.cpp
     458    jit/JITDivGenerator.cpp
    458459    jit/JITExceptions.cpp
    459460    jit/JITInlineCacheGenerator.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r192831 r192836  
     12015-11-30  Mark Lam  <mark.lam@apple.com>
     2
     3        Snippefy op_div for the baseline JIT.
     4        https://bugs.webkit.org/show_bug.cgi?id=151607
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * CMakeLists.txt:
     9        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     10        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     11        * JavaScriptCore.xcodeproj/project.pbxproj:
     12
     13        * jit/JIT.h:
     14        * jit/JITArithmetic.cpp:
     15        (JSC::JIT::emit_op_div):
     16        (JSC::JIT::emitSlow_op_div):
     17        (JSC::JIT::compileBinaryArithOpSlowCase): Deleted.
     18
     19        * jit/JITArithmetic32_64.cpp:
     20        (JSC::JIT::emitBinaryDoubleOp):
     21        (JSC::JIT::emit_op_div): Deleted.
     22        (JSC::JIT::emitSlow_op_div): Deleted.
     23        - Removed the 32-bit specific op_div implementation.  The 64-bit version with the
     24          op_div snippet can now service both 32-bit and 64-bit.
     25 
     26        * jit/JITDivGenerator.cpp: Added.
     27        (JSC::JITDivGenerator::loadOperand):
     28        (JSC::JITDivGenerator::generateFastPath):
     29        * jit/JITDivGenerator.h: Added.
     30        (JSC::JITDivGenerator::JITDivGenerator):
     31        (JSC::JITDivGenerator::didEmitFastPath):
     32        (JSC::JITDivGenerator::endJumpList):
     33        (JSC::JITDivGenerator::slowPathJumpList):
     34 
     35        * jit/JITInlines.h:
     36        (JSC::JIT::getOperandConstantDouble): Added.
     37 
     38        * jit/SnippetOperand.h: Added.
     39        (JSC::SnippetOperand::SnippetOperand):
     40        (JSC::SnippetOperand::mightBeNumber):
     41        (JSC::SnippetOperand::definitelyIsNumber):
     42        (JSC::SnippetOperand::isConst):
     43        (JSC::SnippetOperand::isConstInt32):
     44        (JSC::SnippetOperand::isConstDouble):
     45        (JSC::SnippetOperand::asRawBits):
     46        (JSC::SnippetOperand::asConstInt32):
     47        (JSC::SnippetOperand::asConstDouble):
     48        (JSC::SnippetOperand::setConstInt32):
     49        (JSC::SnippetOperand::setConstDouble):
     50        - The SnippetOperand encapsulates operand constness, const type, and profiling
     51          information.  As a result:
     52          1. The argument list to the JITDivGenerator constructor is now more concise.
     53          2. The logic of the JITDivGenerator is now less verbose and easier to express.
     54
     55        * parser/ResultType.h:
     56        (JSC::ResultType::isInt32):
     57        (JSC::ResultType::definitelyIsNumber):
     58        (JSC::ResultType::definitelyIsString):
     59        (JSC::ResultType::definitelyIsBoolean):
     60        (JSC::ResultType::mightBeNumber):
     61        (JSC::ResultType::isNotNumber):
     62        - Made these functions const because they were always meant to be const.
     63          This also allows me to enforce constness in the SnippetOperand.
     64
    1652015-11-30  Sukolsak Sakshuwong  <sukolsak@gmail.com>
    266
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r192600 r192836  
    648648    <ClCompile Include="..\jit\JITCode.cpp" />
    649649    <ClCompile Include="..\jit\JITDisassembler.cpp" />
     650    <ClCompile Include="..\jit\JITDivGenerator.cpp" />
    650651    <ClCompile Include="..\jit\JITExceptions.cpp" />
    651652    <ClCompile Include="..\jit\JITInlineCacheGenerator.cpp" />
     
    14661467    <ClInclude Include="..\jit\JITCompilationEffort.h" />
    14671468    <ClInclude Include="..\jit\JITDisassembler.h" />
     1469    <ClInclude Include="..\jit\JITDivGenerator.h" />
    14681470    <ClInclude Include="..\jit\JITExceptions.h" />
    14691471    <ClInclude Include="..\jit\JITInlineCacheGenerator.h" />
     
    14861488    <ClInclude Include="..\jit\Repatch.h" />
    14871489    <ClInclude Include="..\jit\ScratchRegisterAllocator.h" />
     1490    <ClInclude Include="..\jit\SnippetOperand.h" />
    14881491    <ClInclude Include="..\jit\SpecializedThunkJIT.h" />
    14891492    <ClInclude Include="..\jit\TempRegisterSet.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r192600 r192836  
    442442      <Filter>jit</Filter>
    443443    </ClCompile>
     444    <ClCompile Include="..\jit\JITDivGenerator.cpp">
     445      <Filter>jit</Filter>
     446    </ClCompile>
    444447    <ClCompile Include="..\jit\JITExceptions.cpp">
    445448      <Filter>jit</Filter>
     
    25172520      <Filter>jit</Filter>
    25182521    </ClInclude>
     2522    <ClInclude Include="..\jit\JITDivGenerator.h">
     2523      <Filter>jit</Filter>
     2524    </ClInclude>
    25192525    <ClInclude Include="..\jit\JITExceptions.h">
    25202526      <Filter>jit</Filter>
     
    25422548    </ClInclude>
    25432549    <ClInclude Include="..\jit\SpecializedThunkJIT.h">
     2550      <Filter>jit</Filter>
     2551    </ClInclude>
     2552    <ClInclude Include="..\jit\SnippetOperand.h">
    25442553      <Filter>jit</Filter>
    25452554    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r192816 r192836  
    19731973                FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */; };
    19741974                FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */; };
     1975                FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0B1C0229230038BBCA /* JITDivGenerator.h */; settings = {ASSET_TAGS = (); }; };
     1976                FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */; settings = {ASSET_TAGS = (); }; };
     1977                FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */; settings = {ASSET_TAGS = (); }; };
    19751978                FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; };
    19761979                FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1C0FFE1B194FD100B53FCA /* Exception.cpp */; };
     
    41134116                FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITMulGenerator.cpp; sourceTree = "<group>"; };
    41144117                FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMulGenerator.h; sourceTree = "<group>"; };
     4118                FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITDivGenerator.cpp; sourceTree = "<group>"; };
     4119                FE187A0B1C0229230038BBCA /* JITDivGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDivGenerator.h; sourceTree = "<group>"; };
     4120                FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnippetOperand.h; sourceTree = "<group>"; };
    41154121                FE1C0FFC1B193E9800B53FCA /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
    41164122                FE1C0FFE1B194FD100B53FCA /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = "<group>"; };
     
    47924798                                0FAF7EFA165BA919000C8455 /* JITDisassembler.cpp */,
    47934799                                0FAF7EFB165BA919000C8455 /* JITDisassembler.h */,
     4800                                FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */,
     4801                                FE187A0B1C0229230038BBCA /* JITDivGenerator.h */,
    47944802                                0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
    47954803                                0F46808014BA572700BFE272 /* JITExceptions.h */,
     
    48334841                                0FEE98401A8865B600754E93 /* SetupVarargsFrame.h */,
    48344842                                A709F2EF17A0AC0400512E98 /* SlowPathCall.h */,
     4843                                FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */,
    48354844                                A7386551118697B400540279 /* SpecializedThunkJIT.h */,
    48364845                                A7FF647A18C52E8500B55307 /* SpillRegistersMode.h */,
     
    71987207                                0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */,
    71997208                                C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */,
     7209                                FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */,
    72007210                                2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */,
    72017211                                A5339EC91BB4B4600054F005 /* HeapObserver.h in Headers */,
     
    72617271                                A18193E41B4E0CDB00FC1029 /* IntlCollatorPrototype.lut.h in Headers */,
    72627272                                A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */,
     7273                                FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */,
    72637274                                A1587D701B4DC14100D69849 /* IntlDateTimeFormatConstructor.h in Headers */,
    72647275                                A1587D751B4DC1C600D69849 /* IntlDateTimeFormatConstructor.lut.h in Headers */,
     
    85998610                                0FD120331A8C85BD000F5280 /* FTLJSCallVarargs.cpp in Sources */,
    86008611                                62774DAA1B8D4B190006F05A /* FTLJSTailCall.cpp in Sources */,
     8612                                FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */,
    86018613                                0FB4FB731BC843140025CA5A /* FTLLazySlowPath.cpp in Sources */,
    86028614                                0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r192814 r192836  
    405405
    406406        int32_t getOperandConstantInt(int src);
     407        double getOperandConstantDouble(int src);
    407408
    408409#if USE(JSVALUE32_64)
     
    463464
    464465        void emitTagBool(RegisterID);
    465         void compileBinaryArithOpSlowCase(Instruction*, OpcodeID, Vector<SlowCaseEntry>::iterator&, int dst, int src1, int src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
    466466
    467467        void compileGetByIdHotPath(int baseVReg, const Identifier*);
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r192600 r192836  
    3131#include "CodeBlock.h"
    3232#include "JITAddGenerator.h"
     33#include "JITDivGenerator.h"
    3334#include "JITInlines.h"
    3435#include "JITMulGenerator.h"
     
    662663/* ------------------------------ END: OP_MOD ------------------------------ */
    663664
    664 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
    665 
    666 void JIT::compileBinaryArithOpSlowCase(Instruction* currentInstruction, OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, int result, int op1, int op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
    667 {
    668     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
    669     COMPILE_ASSERT(((TagTypeNumber + DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
    670 
    671     Jump notImm1;
    672     Jump notImm2;
    673     if (op1HasImmediateIntFastCase) {
    674         notImm2 = getSlowCase(iter);
    675     } else if (op2HasImmediateIntFastCase) {
    676         notImm1 = getSlowCase(iter);
    677     } else {
    678         notImm1 = getSlowCase(iter);
    679         notImm2 = getSlowCase(iter);
    680     }
    681 
    682     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
    683 
    684     Label stubFunctionCall(this);
    685 
    686     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
    687     slowPathCall.call();
    688     Jump end = jump();
    689 
    690     if (op1HasImmediateIntFastCase) {
    691         notImm2.link(this);
    692         if (!types.second().definitelyIsNumber())
    693             emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);
    694         emitGetVirtualRegister(op1, regT1);
    695         convertInt32ToDouble(regT1, fpRegT1);
    696         add64(tagTypeNumberRegister, regT0);
    697         move64ToDouble(regT0, fpRegT2);
    698     } else if (op2HasImmediateIntFastCase) {
    699         notImm1.link(this);
    700         if (!types.first().definitelyIsNumber())
    701             emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);
    702         emitGetVirtualRegister(op2, regT1);
    703         convertInt32ToDouble(regT1, fpRegT1);
    704         add64(tagTypeNumberRegister, regT0);
    705         move64ToDouble(regT0, fpRegT2);
    706     } else {
    707         // if we get here, eax is not an int32, edx not yet checked.
    708         notImm1.link(this);
    709         if (!types.first().definitelyIsNumber())
    710             emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);
    711         if (!types.second().definitelyIsNumber())
    712             emitJumpIfNotNumber(regT1).linkTo(stubFunctionCall, this);
    713         add64(tagTypeNumberRegister, regT0);
    714         move64ToDouble(regT0, fpRegT1);
    715         Jump op2isDouble = emitJumpIfNotInt(regT1);
    716         convertInt32ToDouble(regT1, fpRegT2);
    717         Jump op2wasInteger = jump();
    718 
    719         // if we get here, eax IS an int32, edx is not.
    720         notImm2.link(this);
    721         if (!types.second().definitelyIsNumber())
    722             emitJumpIfNotNumber(regT1).linkTo(stubFunctionCall, this);
    723         convertInt32ToDouble(regT0, fpRegT1);
    724         op2isDouble.link(this);
    725         add64(tagTypeNumberRegister, regT1);
    726         move64ToDouble(regT1, fpRegT2);
    727         op2wasInteger.link(this);
    728     }
    729 
    730     ASSERT_UNUSED(opcodeID, opcodeID == op_div);
    731     divDouble(fpRegT2, fpRegT1);
    732 
    733     moveDoubleTo64(fpRegT1, regT0);
    734     sub64(tagTypeNumberRegister, regT0);
    735     emitPutVirtualRegister(result, regT0);
    736 
    737     end.link(this);
    738 }
    739 
    740 void JIT::emit_op_div(Instruction* currentInstruction)
    741 {
    742     int dst = currentInstruction[1].u.operand;
    743     int op1 = currentInstruction[2].u.operand;
    744     int op2 = currentInstruction[3].u.operand;
    745     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    746 
    747     if (isOperandConstantDouble(op1)) {
    748         emitGetVirtualRegister(op1, regT0);
    749         add64(tagTypeNumberRegister, regT0);
    750         move64ToDouble(regT0, fpRegT0);
    751     } else if (isOperandConstantInt(op1)) {
    752         emitLoadInt32ToDouble(op1, fpRegT0);
    753     } else {
    754         emitGetVirtualRegister(op1, regT0);
    755         if (!types.first().definitelyIsNumber())
    756             emitJumpSlowCaseIfNotNumber(regT0);
    757         Jump notInt = emitJumpIfNotInt(regT0);
    758         convertInt32ToDouble(regT0, fpRegT0);
    759         Jump skipDoubleLoad = jump();
    760         notInt.link(this);
    761         add64(tagTypeNumberRegister, regT0);
    762         move64ToDouble(regT0, fpRegT0);
    763         skipDoubleLoad.link(this);
    764     }
    765 
    766     if (isOperandConstantDouble(op2)) {
    767         emitGetVirtualRegister(op2, regT1);
    768         add64(tagTypeNumberRegister, regT1);
    769         move64ToDouble(regT1, fpRegT1);
    770     } else if (isOperandConstantInt(op2)) {
    771         emitLoadInt32ToDouble(op2, fpRegT1);
    772     } else {
    773         emitGetVirtualRegister(op2, regT1);
    774         if (!types.second().definitelyIsNumber())
    775             emitJumpSlowCaseIfNotNumber(regT1);
    776         Jump notInt = emitJumpIfNotInt(regT1);
    777         convertInt32ToDouble(regT1, fpRegT1);
    778         Jump skipDoubleLoad = jump();
    779         notInt.link(this);
    780         add64(tagTypeNumberRegister, regT1);
    781         move64ToDouble(regT1, fpRegT1);
    782         skipDoubleLoad.link(this);
    783     }
    784     divDouble(fpRegT1, fpRegT0);
    785    
    786     // Is the result actually an integer? The DFG JIT would really like to know. If it's
    787     // not an integer, we increment a count. If this together with the slow case counter
    788     // are below threshold then the DFG JIT will compile this division with a specualtion
    789     // that the remainder is zero.
    790    
    791     // As well, there are cases where a double result here would cause an important field
    792     // in the heap to sometimes have doubles in it, resulting in double predictions getting
    793     // propagated to a use site where it might cause damage (such as the index to an array
    794     // access). So if we are DFG compiling anything in the program, we want this code to
    795     // ensure that it produces integers whenever possible.
    796    
    797     JumpList notInteger;
    798     branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1);
    799     // If we've got an integer, we might as well make that the result of the division.
    800     emitTagInt(regT0, regT0);
    801     Jump isInteger = jump();
    802     notInteger.link(this);
    803     moveDoubleTo64(fpRegT0, regT0);
    804     Jump doubleZero = branchTest64(Zero, regT0);
    805     add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
    806     sub64(tagTypeNumberRegister, regT0);
    807     Jump trueDouble = jump();
    808     doubleZero.link(this);
    809     move(tagTypeNumberRegister, regT0);
    810     trueDouble.link(this);
    811     isInteger.link(this);
    812 
    813     emitPutVirtualRegister(dst, regT0);
    814 }
    815 
    816 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    817 {
    818     int op1 = currentInstruction[2].u.operand;
    819     int op2 = currentInstruction[3].u.operand;
    820     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    821     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
    822         if (!ASSERT_DISABLED)
    823             abortWithReason(JITDivOperandsAreNotNumbers);
    824         return;
    825     }
    826     if (!isOperandConstantDouble(op1) && !isOperandConstantInt(op1)) {
    827         if (!types.first().definitelyIsNumber())
    828             linkSlowCase(iter);
    829     }
    830     if (!isOperandConstantDouble(op2) && !isOperandConstantInt(op2)) {
    831         if (!types.second().definitelyIsNumber())
    832             linkSlowCase(iter);
    833     }
    834     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
    835     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
    836     slowPathCall.call();
    837 }
    838 
    839665#endif // USE(JSVALUE64)
    840666
     
    907733}
    908734
    909 void JIT::emit_op_mul(Instruction* currentInstruction)
     735void JIT::emit_op_div(Instruction* currentInstruction)
    910736{
    911737    int result = currentInstruction[1].u.operand;
     
    928754#endif
    929755
    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)
     756    uint32_t* profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter;
     757
     758    SnippetOperand leftOperand(types.first());
     759    SnippetOperand rightOperand(types.second());
     760
     761    if (isOperandConstantInt(op1))
     762        leftOperand.setConstInt32(getOperandConstantInt(op1));
     763#if USE(JSVALUE64)
     764    else if (isOperandConstantDouble(op1))
     765        leftOperand.setConstDouble(getOperandConstantDouble(op1));
     766#endif
     767
     768    if (isOperandConstantInt(op2))
     769        rightOperand.setConstInt32(getOperandConstantInt(op2));
     770#if USE(JSVALUE64)
     771    else if (isOperandConstantDouble(op2))
     772        rightOperand.setConstDouble(getOperandConstantDouble(op2));
     773#endif
     774
     775    ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
     776
     777    if (!leftOperand.isConst())
     778        emitGetVirtualRegister(op1, leftRegs);
     779    if (!rightOperand.isConst())
    952780        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,
     781
     782    JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
    962783        fpRegT0, fpRegT1, scratchGPR, scratchFPR, profilingCounter);
    963784
     
    972793        ASSERT(gen.endJumpList().empty());
    973794        ASSERT(gen.slowPathJumpList().empty());
    974         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
     795        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
    975796        slowPathCall.call();
    976797    }
    977798}
    978799
    979 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     800void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    980801{
    981802    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
    982    
    983     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
    984     slowPathCall.call();
    985 }
    986 
    987 void JIT::emit_op_sub(Instruction* currentInstruction)
     803
     804    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
     805    slowPathCall.call();
     806}
     807
     808void JIT::emit_op_mul(Instruction* currentInstruction)
    988809{
    989810    int result = currentInstruction[1].u.operand;
     
    1006827#endif
    1007828
     829    bool leftIsConstInt32 = isOperandConstantInt(op1);
     830    bool rightIsConstInt32 = isOperandConstantInt(op2);
     831    ResultType leftType = types.first();
     832    ResultType rightType = types.second();
     833    int32_t leftConstInt32 = 0;
     834    int32_t rightConstInt32 = 0;
     835
     836    uint32_t* profilingCounter = nullptr;
     837    if (shouldEmitProfiling())
     838        profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter;
     839
     840    ASSERT(!leftIsConstInt32 || !rightIsConstInt32);
     841
     842    if (leftIsConstInt32)
     843        leftConstInt32 = getOperandConstantInt(op1);
     844    if (rightIsConstInt32)
     845        rightConstInt32 = getOperandConstantInt(op2);
     846
     847    bool leftIsPositiveConstInt32 = leftIsConstInt32 && (leftConstInt32 > 0);
     848    bool rightIsPositiveConstInt32 = rightIsConstInt32 && (rightConstInt32 > 0);
     849
     850    if (leftIsPositiveConstInt32)
     851        emitGetVirtualRegister(op2, rightRegs);
     852    else if (rightIsPositiveConstInt32)
     853        emitGetVirtualRegister(op1, leftRegs);
     854    else {
     855        emitGetVirtualRegister(op1, leftRegs);
     856        emitGetVirtualRegister(op2, rightRegs);
     857    }
     858
     859    JITMulGenerator gen(resultRegs, leftRegs, rightRegs, leftType, rightType,
     860        leftIsPositiveConstInt32, rightIsPositiveConstInt32, leftConstInt32, rightConstInt32,
     861        fpRegT0, fpRegT1, scratchGPR, scratchFPR, profilingCounter);
     862
     863    gen.generateFastPath(*this);
     864
     865    if (gen.didEmitFastPath()) {
     866        gen.endJumpList().link(this);
     867        emitPutVirtualRegister(result, resultRegs);
     868
     869        addSlowCase(gen.slowPathJumpList());
     870    } else {
     871        ASSERT(gen.endJumpList().empty());
     872        ASSERT(gen.slowPathJumpList().empty());
     873        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
     874        slowPathCall.call();
     875    }
     876}
     877
     878void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     879{
     880    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
     881   
     882    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
     883    slowPathCall.call();
     884}
     885
     886void JIT::emit_op_sub(Instruction* currentInstruction)
     887{
     888    int result = currentInstruction[1].u.operand;
     889    int op1 = currentInstruction[2].u.operand;
     890    int op2 = currentInstruction[3].u.operand;
     891    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     892
     893#if USE(JSVALUE64)
     894    JSValueRegs leftRegs = JSValueRegs(regT0);
     895    JSValueRegs rightRegs = JSValueRegs(regT1);
     896    JSValueRegs resultRegs = leftRegs;
     897    GPRReg scratchGPR = regT2;
     898    FPRReg scratchFPR = InvalidFPRReg;
     899#else
     900    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
     901    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
     902    JSValueRegs resultRegs = leftRegs;
     903    GPRReg scratchGPR = regT4;
     904    FPRReg scratchFPR = fpRegT2;
     905#endif
     906
    1008907    emitGetVirtualRegister(op1, leftRegs);
    1009908    emitGetVirtualRegister(op2, rightRegs);
  • trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp

    r192600 r192836  
    479479}
    480480
    481 // Addition (+)
    482 
    483481void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, int dst, int op1, int op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
    484482{
     
    513511        doTheMath.link(this);
    514512        switch (opcodeID) {
    515             case op_div: {
    516                 emitLoadDouble(op1, fpRegT1);
    517                 divDouble(fpRegT0, fpRegT1);
    518 
    519                 // Is the result actually an integer? The DFG JIT would really like to know. If it's
    520                 // not an integer, we increment a count. If this together with the slow case counter
    521                 // are below threshold then the DFG JIT will compile this division with a specualtion
    522                 // that the remainder is zero.
    523                
    524                 // As well, there are cases where a double result here would cause an important field
    525                 // in the heap to sometimes have doubles in it, resulting in double predictions getting
    526                 // propagated to a use site where it might cause damage (such as the index to an array
    527                 // access). So if we are DFG compiling anything in the program, we want this code to
    528                 // ensure that it produces integers whenever possible.
    529                
    530                 // FIXME: This will fail to convert to integer if the result is zero. We should
    531                 // distinguish between positive zero and negative zero here.
    532                
    533                 JumpList notInteger;
    534                 branchConvertDoubleToInt32(fpRegT1, regT2, notInteger, fpRegT0);
    535                 // If we've got an integer, we might as well make that the result of the division.
    536                 emitStoreInt32(dst, regT2);
    537                 Jump isInteger = jump();
    538                 notInteger.link(this);
    539                 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
    540                 emitStoreDouble(dst, fpRegT1);
    541                 isInteger.link(this);
    542                 break;
    543             }
    544513            case op_jless:
    545514                emitLoadDouble(op1, fpRegT2);
     
    599568        // Do the math.
    600569        switch (opcodeID) {
    601             case op_div: {
    602                 emitLoadDouble(op2, fpRegT2);
    603                 divDouble(fpRegT2, fpRegT0);
    604                 // Is the result actually an integer? The DFG JIT would really like to know. If it's
    605                 // not an integer, we increment a count. If this together with the slow case counter
    606                 // are below threshold then the DFG JIT will compile this division with a specualtion
    607                 // that the remainder is zero.
    608                
    609                 // As well, there are cases where a double result here would cause an important field
    610                 // in the heap to sometimes have doubles in it, resulting in double predictions getting
    611                 // propagated to a use site where it might cause damage (such as the index to an array
    612                 // access). So if we are DFG compiling anything in the program, we want this code to
    613                 // ensure that it produces integers whenever possible.
    614                
    615                 // FIXME: This will fail to convert to integer if the result is zero. We should
    616                 // distinguish between positive zero and negative zero here.
    617                
    618                 JumpList notInteger;
    619                 branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);
    620                 // If we've got an integer, we might as well make that the result of the division.
    621                 emitStoreInt32(dst, regT2);
    622                 Jump isInteger = jump();
    623                 notInteger.link(this);
    624                 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
    625                 emitStoreDouble(dst, fpRegT0);
    626                 isInteger.link(this);
    627                 break;
    628             }
    629570            case op_jless:
    630571                emitLoadDouble(op2, fpRegT1);
     
    665606
    666607    end.link(this);
    667 }
    668 
    669 // Division (/)
    670 
    671 void JIT::emit_op_div(Instruction* currentInstruction)
    672 {
    673     int dst = currentInstruction[1].u.operand;
    674     int op1 = currentInstruction[2].u.operand;
    675     int op2 = currentInstruction[3].u.operand;
    676     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    677 
    678     m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
    679 
    680     if (!supportsFloatingPoint()) {
    681         addSlowCase(jump());
    682         return;
    683     }
    684 
    685     // Int32 divide.
    686     JumpList notInt32Op1;
    687     JumpList notInt32Op2;
    688 
    689     JumpList end;
    690 
    691     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
    692 
    693     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
    694     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    695 
    696     convertInt32ToDouble(regT0, fpRegT0);
    697     convertInt32ToDouble(regT2, fpRegT1);
    698     divDouble(fpRegT1, fpRegT0);
    699     // Is the result actually an integer? The DFG JIT would really like to know. If it's
    700     // not an integer, we increment a count. If this together with the slow case counter
    701     // are below threshold then the DFG JIT will compile this division with a specualtion
    702     // that the remainder is zero.
    703    
    704     // As well, there are cases where a double result here would cause an important field
    705     // in the heap to sometimes have doubles in it, resulting in double predictions getting
    706     // propagated to a use site where it might cause damage (such as the index to an array
    707     // access). So if we are DFG compiling anything in the program, we want this code to
    708     // ensure that it produces integers whenever possible.
    709    
    710     // FIXME: This will fail to convert to integer if the result is zero. We should
    711     // distinguish between positive zero and negative zero here.
    712    
    713     JumpList notInteger;
    714     branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);
    715     // If we've got an integer, we might as well make that the result of the division.
    716     emitStoreInt32(dst, regT2);
    717     end.append(jump());
    718     notInteger.link(this);
    719     add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
    720     emitStoreDouble(dst, fpRegT0);
    721     end.append(jump());
    722 
    723     // Double divide.
    724     emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);
    725     end.link(this);
    726 }
    727 
    728 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    729 {
    730     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    731 
    732     if (!supportsFloatingPoint())
    733         linkSlowCase(iter);
    734     else {
    735         if (!types.first().definitelyIsNumber())
    736             linkSlowCase(iter); // double check
    737 
    738         if (!types.second().definitelyIsNumber()) {
    739             linkSlowCase(iter); // int32 check
    740             linkSlowCase(iter); // double check
    741         }
    742     }
    743 
    744     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
    745     slowPathCall.call();
    746608}
    747609
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r191905 r192836  
    981981}
    982982
     983ALWAYS_INLINE double JIT::getOperandConstantDouble(int src)
     984{
     985    return getConstantOperand(src).asDouble();
     986}
     987
    983988#if USE(JSVALUE32_64)
    984989
  • trunk/Source/JavaScriptCore/parser/ResultType.h

    r191224 r192836  
    5050
    5151    public:
    52         bool isInt32()
     52        bool isInt32() const
    5353        {
    5454            return m_type & TypeInt32;
    5555        }
    5656
    57         bool definitelyIsNumber()
     57        bool definitelyIsNumber() const
    5858        {
    5959            return (m_type & TypeBits) == TypeMaybeNumber;
    6060        }
    6161       
    62         bool definitelyIsString()
     62        bool definitelyIsString() const
    6363        {
    6464            return (m_type & TypeBits) == TypeMaybeString;
    6565        }
    6666
    67         bool definitelyIsBoolean()
     67        bool definitelyIsBoolean() const
    6868        {
    6969            return (m_type & TypeBits) == TypeMaybeBool;
    7070        }
    7171
    72         bool mightBeNumber()
     72        bool mightBeNumber() const
    7373        {
    7474            return m_type & TypeMaybeNumber;
    7575        }
    7676
    77         bool isNotNumber()
     77        bool isNotNumber() const
    7878        {
    7979            return !mightBeNumber();
Note: See TracChangeset for help on using the changeset viewer.