Changeset 252422 in webkit


Ignore:
Timestamp:
Nov 13, 2019 12:07:29 PM (4 years ago)
Author:
rmorisset@apple.com
Message:

Split ArithProfile into a Unary and a Binary version
https://bugs.webkit.org/show_bug.cgi?id=202832
<rdar://problem/56266847>

Reviewed by Keith Miller.

JSTests:

The new test (kindly provided by Mark Lam) catches the metadata corruption that used to happen in the previous version of this patch.

  • stress/regress-57020338.js: Added.

Source/JavaScriptCore:

ArithProfile was for a long time only used for add/sub/mul/div, but recently it started being used for negate. And it will soon also have to be used for inc and dec due to BigInt.
So in this patch I make a separate version that only has the data for a single argument, and thus takes half as much memory.

After discussing this change with Phil I realized that the ResultType(s) that were taking space in ArithProfile are not needed: they never change and a copy is already in the bytecode instruction itself.
Removing them allowed shrinking both kinds of ArithProfile to fit in 16 bits (9 and 13 respectively).
I kept the two kinds separate because they may shrink or grow independently in the future.

This also required adding the "orh" instruction to the offline assembler, to set bits in the ArithProfile.
This in turn motivated the addition of "storeh", as on RISC platforms "orh" on a memory location is actually loadh -> orh -> storeh.

Finally it required adding support for or16(TrustedImm32, AbsoluteAddress) in the MacroAssembler for the ICs.
Instead of directly calling it (like we used to do with or32), I introduced ArithProfile::emitUnconditionalSet, so that if either ArithProfile ever changes in size again we'll have fewer places to change.

  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::or16):

  • assembler/MacroAssemblerARMv7.h:

(JSC::MacroAssemblerARMv7::or16):

  • assembler/MacroAssemblerMIPS.h:

(JSC::MacroAssemblerMIPS::or16):

  • assembler/MacroAssemblerX86.h:

(JSC::MacroAssemblerX86::or16):

  • assembler/MacroAssemblerX86_64.h:

(JSC::MacroAssemblerX86_64::or16):

  • assembler/testmasm.cpp:

(JSC::testOrImmMem):
(JSC::run):

  • bytecode/ArithProfile.cpp:

(JSC::ArithProfile<BitfieldType>::emitObserveResult):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetDouble const):
(JSC::ArithProfile<BitfieldType>::emitSetDouble const):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetNonNumeric const):
(JSC::ArithProfile<BitfieldType>::emitSetNonNumeric const):
(JSC::ArithProfile<BitfieldType>::shouldEmitSetBigInt const):
(JSC::ArithProfile<BitfieldType>::emitSetBigInt const):
(JSC::ArithProfile<BitfieldType>::emitUnconditionalSet const):
(WTF::printInternal):

  • bytecode/ArithProfile.h:

(JSC::ArithProfile::didObserveNonInt32 const):
(JSC::ArithProfile::didObserveDouble const):
(JSC::ArithProfile::didObserveNonNegZeroDouble const):
(JSC::ArithProfile::didObserveNegZeroDouble const):
(JSC::ArithProfile::didObserveNonNumeric const):
(JSC::ArithProfile::didObserveBigInt const):
(JSC::ArithProfile::didObserveInt32Overflow const):
(JSC::ArithProfile::didObserveInt52Overflow const):
(JSC::ArithProfile::setObservedNonNegZeroDouble):
(JSC::ArithProfile::setObservedNegZeroDouble):
(JSC::ArithProfile::setObservedNonNumeric):
(JSC::ArithProfile::setObservedBigInt):
(JSC::ArithProfile::setObservedInt32Overflow):
(JSC::ArithProfile::setObservedInt52Overflow):
(JSC::ArithProfile::observeResult):
(JSC::ArithProfile::addressOfBits const):
(JSC::ArithProfile::bits const):
(JSC::ArithProfile::ArithProfile):
(JSC::ArithProfile::hasBits const):
(JSC::ArithProfile::setBit):
(JSC::UnaryArithProfile::UnaryArithProfile):
(JSC::UnaryArithProfile::observedIntBits):
(JSC::UnaryArithProfile::observedNumberBits):
(JSC::UnaryArithProfile::argObservedType const):
(JSC::UnaryArithProfile::setArgObservedType):
(JSC::UnaryArithProfile::argSawInt32):
(JSC::UnaryArithProfile::argSawNumber):
(JSC::UnaryArithProfile::argSawNonNumber):
(JSC::UnaryArithProfile::observeArg):
(JSC::UnaryArithProfile::isObservedTypeEmpty):
(JSC::BinaryArithProfile::BinaryArithProfile):
(JSC::BinaryArithProfile::observedIntIntBits):
(JSC::BinaryArithProfile::observedNumberIntBits):
(JSC::BinaryArithProfile::observedIntNumberBits):
(JSC::BinaryArithProfile::observedNumberNumberBits):
(JSC::BinaryArithProfile::setLhsObservedType):
(JSC::BinaryArithProfile::setRhsObservedType):
(JSC::BinaryArithProfile::observeLHS):
(JSC::BinaryArithProfile::observeLHSAndRHS):
(JSC::BinaryArithProfile::isObservedTypeEmpty):

  • bytecode/BytecodeList.rb:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::addJITAddIC):
(JSC::CodeBlock::addJITMulIC):
(JSC::CodeBlock::addJITSubIC):
(JSC::CodeBlock::addJITNegIC):
(JSC::CodeBlock::binaryArithProfileForBytecodeIndex):
(JSC::CodeBlock::unaryArithProfileForBytecodeIndex):
(JSC::CodeBlock::binaryArithProfileForPC):
(JSC::CodeBlock::unaryArithProfileForPC):
(JSC::CodeBlock::couldTakeSpecialArithFastCase):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::addMathIC):

  • bytecode/Fits.h:
  • bytecode/MethodOfGettingAValueProfile.cpp:

(JSC::MethodOfGettingAValueProfile::emitReportValue const):
(JSC::MethodOfGettingAValueProfile::reportValue):

  • bytecode/MethodOfGettingAValueProfile.h:

(JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitUnaryOp):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::UnaryOpNode::emitBytecode):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::makeDivSafe):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::methodOfGettingAValueProfileFor):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileValueAdd):
(JSC::DFG::SpeculativeJIT::compileValueSub):
(JSC::DFG::SpeculativeJIT::compileValueNegate):
(JSC::DFG::SpeculativeJIT::compileValueMul):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
(JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
(JSC::FTL::DFG::LowerDFGToB3::compileUnaryMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileBinaryMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub):
(JSC::FTL::DFG::LowerDFGToB3::compileValueNegate):

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

(JSC::JITAddGenerator::generateInline):
(JSC::JITAddGenerator::generateFastPath):

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

(JSC::JIT::emit_op_negate):
(JSC::JIT::emit_op_add):
(JSC::JIT::emitMathICFast):
(JSC::JIT::emitMathICSlow):
(JSC::JIT::emit_op_div):
(JSC::JIT::emit_op_mul):
(JSC::JIT::emit_op_sub):

  • jit/JITDivGenerator.cpp:

(JSC::JITDivGenerator::generateFastPath):

  • jit/JITDivGenerator.h:

(JSC::JITDivGenerator::JITDivGenerator):

  • jit/JITInlines.h:

(JSC::JIT::copiedArithProfile):

  • jit/JITMathIC.h:

(JSC::JITMathIC::JITMathIC):
(JSC::JITMathIC::generateInline):
(JSC::JITMathIC::arithProfile const):
(JSC::JITBinaryMathIC::JITBinaryMathIC):
(JSC::JITUnaryMathIC::JITUnaryMathIC):

  • jit/JITMulGenerator.cpp:

(JSC::JITMulGenerator::generateInline):
(JSC::JITMulGenerator::generateFastPath):

  • jit/JITMulGenerator.h:
  • jit/JITNegGenerator.cpp:

(JSC::JITNegGenerator::generateInline):
(JSC::JITNegGenerator::generateFastPath):

  • jit/JITNegGenerator.h:
  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/JITSubGenerator.cpp:

(JSC::JITSubGenerator::generateInline):
(JSC::JITSubGenerator::generateFastPath):

  • jit/JITSubGenerator.h:
  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LLIntOffsetsExtractor.cpp:

(JSC::LLIntOffsetsExtractor::dummy):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • offlineasm/arm.rb:
  • offlineasm/arm64.rb:
  • offlineasm/cloop.rb:
  • offlineasm/instructions.rb:
  • offlineasm/mips.rb:
  • offlineasm/risc.rb:
  • offlineasm/x86.rb:
  • parser/ResultType.h:

(JSC::ResultType::ResultType):

  • runtime/CommonSlowPaths.cpp:

(JSC::updateArithProfileForUnaryArithOp):
(JSC::updateArithProfileForBinaryArithOp):
(JSC::SLOW_PATH_DECL):

Location:
trunk
Files:
1 added
53 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r252416 r252422  
     12019-11-13  Robin Morisset  <rmorisset@apple.com>
     2
     3        Split ArithProfile into a Unary and a Binary version
     4        https://bugs.webkit.org/show_bug.cgi?id=202832
     5        <rdar://problem/56266847>
     6
     7        Reviewed by Keith Miller.
     8
     9        The new test (kindly provided by Mark Lam) catches the metadata corruption that used to happen in the previous version of this patch.
     10
     11        * stress/regress-57020338.js: Added.
     12
    1132019-11-13  Yusuke Suzuki  <ysuzuki@apple.com>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r252421 r252422  
     12019-11-13  Robin Morisset  <rmorisset@apple.com>
     2
     3        Split ArithProfile into a Unary and a Binary version
     4        https://bugs.webkit.org/show_bug.cgi?id=202832
     5        <rdar://problem/56266847>
     6
     7        Reviewed by Keith Miller.
     8
     9        ArithProfile was for a long time only used for add/sub/mul/div, but recently it started being used for negate. And it will soon also have to be used for inc and dec due to BigInt.
     10        So in this patch I make a separate version that only has the data for a single argument, and thus takes half as much memory.
     11
     12        After discussing this change with Phil I realized that the ResultType(s) that were taking space in ArithProfile are not needed: they never change and a copy is already in the bytecode instruction itself.
     13        Removing them allowed shrinking both kinds of ArithProfile to fit in 16 bits (9 and 13 respectively).
     14        I kept the two kinds separate because they may shrink or grow independently in the future.
     15
     16        This also required adding the "orh" instruction to the offline assembler, to set bits in the ArithProfile.
     17        This in turn motivated the addition of "storeh", as on RISC platforms "orh" on a memory location is actually loadh -> orh -> storeh.
     18
     19        Finally it required adding support for or16(TrustedImm32, AbsoluteAddress) in the MacroAssembler for the ICs.
     20        Instead of directly calling it (like we used to do with or32), I introduced ArithProfile::emitUnconditionalSet, so that if either ArithProfile ever changes in size again we'll have fewer places to change.
     21
     22        * assembler/MacroAssemblerARM64.h:
     23        (JSC::MacroAssemblerARM64::or16):
     24        * assembler/MacroAssemblerARMv7.h:
     25        (JSC::MacroAssemblerARMv7::or16):
     26        * assembler/MacroAssemblerMIPS.h:
     27        (JSC::MacroAssemblerMIPS::or16):
     28        * assembler/MacroAssemblerX86.h:
     29        (JSC::MacroAssemblerX86::or16):
     30        * assembler/MacroAssemblerX86_64.h:
     31        (JSC::MacroAssemblerX86_64::or16):
     32        * assembler/testmasm.cpp:
     33        (JSC::testOrImmMem):
     34        (JSC::run):
     35        * bytecode/ArithProfile.cpp:
     36        (JSC::ArithProfile<BitfieldType>::emitObserveResult):
     37        (JSC::ArithProfile<BitfieldType>::shouldEmitSetDouble const):
     38        (JSC::ArithProfile<BitfieldType>::emitSetDouble const):
     39        (JSC::ArithProfile<BitfieldType>::shouldEmitSetNonNumeric const):
     40        (JSC::ArithProfile<BitfieldType>::emitSetNonNumeric const):
     41        (JSC::ArithProfile<BitfieldType>::shouldEmitSetBigInt const):
     42        (JSC::ArithProfile<BitfieldType>::emitSetBigInt const):
     43        (JSC::ArithProfile<BitfieldType>::emitUnconditionalSet const):
     44        (WTF::printInternal):
     45        * bytecode/ArithProfile.h:
     46        (JSC::ArithProfile::didObserveNonInt32 const):
     47        (JSC::ArithProfile::didObserveDouble const):
     48        (JSC::ArithProfile::didObserveNonNegZeroDouble const):
     49        (JSC::ArithProfile::didObserveNegZeroDouble const):
     50        (JSC::ArithProfile::didObserveNonNumeric const):
     51        (JSC::ArithProfile::didObserveBigInt const):
     52        (JSC::ArithProfile::didObserveInt32Overflow const):
     53        (JSC::ArithProfile::didObserveInt52Overflow const):
     54        (JSC::ArithProfile::setObservedNonNegZeroDouble):
     55        (JSC::ArithProfile::setObservedNegZeroDouble):
     56        (JSC::ArithProfile::setObservedNonNumeric):
     57        (JSC::ArithProfile::setObservedBigInt):
     58        (JSC::ArithProfile::setObservedInt32Overflow):
     59        (JSC::ArithProfile::setObservedInt52Overflow):
     60        (JSC::ArithProfile::observeResult):
     61        (JSC::ArithProfile::addressOfBits const):
     62        (JSC::ArithProfile::bits const):
     63        (JSC::ArithProfile::ArithProfile):
     64        (JSC::ArithProfile::hasBits const):
     65        (JSC::ArithProfile::setBit):
     66        (JSC::UnaryArithProfile::UnaryArithProfile):
     67        (JSC::UnaryArithProfile::observedIntBits):
     68        (JSC::UnaryArithProfile::observedNumberBits):
     69        (JSC::UnaryArithProfile::argObservedType const):
     70        (JSC::UnaryArithProfile::setArgObservedType):
     71        (JSC::UnaryArithProfile::argSawInt32):
     72        (JSC::UnaryArithProfile::argSawNumber):
     73        (JSC::UnaryArithProfile::argSawNonNumber):
     74        (JSC::UnaryArithProfile::observeArg):
     75        (JSC::UnaryArithProfile::isObservedTypeEmpty):
     76        (JSC::BinaryArithProfile::BinaryArithProfile):
     77        (JSC::BinaryArithProfile::observedIntIntBits):
     78        (JSC::BinaryArithProfile::observedNumberIntBits):
     79        (JSC::BinaryArithProfile::observedIntNumberBits):
     80        (JSC::BinaryArithProfile::observedNumberNumberBits):
     81        (JSC::BinaryArithProfile::setLhsObservedType):
     82        (JSC::BinaryArithProfile::setRhsObservedType):
     83        (JSC::BinaryArithProfile::observeLHS):
     84        (JSC::BinaryArithProfile::observeLHSAndRHS):
     85        (JSC::BinaryArithProfile::isObservedTypeEmpty):
     86        * bytecode/BytecodeList.rb:
     87        * bytecode/CodeBlock.cpp:
     88        (JSC::CodeBlock::addJITAddIC):
     89        (JSC::CodeBlock::addJITMulIC):
     90        (JSC::CodeBlock::addJITSubIC):
     91        (JSC::CodeBlock::addJITNegIC):
     92        (JSC::CodeBlock::binaryArithProfileForBytecodeIndex):
     93        (JSC::CodeBlock::unaryArithProfileForBytecodeIndex):
     94        (JSC::CodeBlock::binaryArithProfileForPC):
     95        (JSC::CodeBlock::unaryArithProfileForPC):
     96        (JSC::CodeBlock::couldTakeSpecialArithFastCase):
     97        * bytecode/CodeBlock.h:
     98        (JSC::CodeBlock::addMathIC):
     99        * bytecode/Fits.h:
     100        * bytecode/MethodOfGettingAValueProfile.cpp:
     101        (JSC::MethodOfGettingAValueProfile::emitReportValue const):
     102        (JSC::MethodOfGettingAValueProfile::reportValue):
     103        * bytecode/MethodOfGettingAValueProfile.h:
     104        (JSC::MethodOfGettingAValueProfile::MethodOfGettingAValueProfile):
     105        * bytecompiler/BytecodeGenerator.cpp:
     106        (JSC::BytecodeGenerator::emitUnaryOp):
     107        * bytecompiler/BytecodeGenerator.h:
     108        * bytecompiler/NodesCodegen.cpp:
     109        (JSC::UnaryOpNode::emitBytecode):
     110        * dfg/DFGByteCodeParser.cpp:
     111        (JSC::DFG::ByteCodeParser::makeSafe):
     112        (JSC::DFG::ByteCodeParser::makeDivSafe):
     113        * dfg/DFGGraph.cpp:
     114        (JSC::DFG::Graph::methodOfGettingAValueProfileFor):
     115        * dfg/DFGSpeculativeJIT.cpp:
     116        (JSC::DFG::SpeculativeJIT::compileValueAdd):
     117        (JSC::DFG::SpeculativeJIT::compileValueSub):
     118        (JSC::DFG::SpeculativeJIT::compileValueNegate):
     119        (JSC::DFG::SpeculativeJIT::compileValueMul):
     120        * ftl/FTLLowerDFGToB3.cpp:
     121        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
     122        (JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
     123        (JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
     124        (JSC::FTL::DFG::LowerDFGToB3::compileUnaryMathIC):
     125        (JSC::FTL::DFG::LowerDFGToB3::compileBinaryMathIC):
     126        (JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub):
     127        (JSC::FTL::DFG::LowerDFGToB3::compileValueNegate):
     128        * jit/JIT.h:
     129        * jit/JITAddGenerator.cpp:
     130        (JSC::JITAddGenerator::generateInline):
     131        (JSC::JITAddGenerator::generateFastPath):
     132        * jit/JITAddGenerator.h:
     133        * jit/JITArithmetic.cpp:
     134        (JSC::JIT::emit_op_negate):
     135        (JSC::JIT::emit_op_add):
     136        (JSC::JIT::emitMathICFast):
     137        (JSC::JIT::emitMathICSlow):
     138        (JSC::JIT::emit_op_div):
     139        (JSC::JIT::emit_op_mul):
     140        (JSC::JIT::emit_op_sub):
     141        * jit/JITDivGenerator.cpp:
     142        (JSC::JITDivGenerator::generateFastPath):
     143        * jit/JITDivGenerator.h:
     144        (JSC::JITDivGenerator::JITDivGenerator):
     145        * jit/JITInlines.h:
     146        (JSC::JIT::copiedArithProfile):
     147        * jit/JITMathIC.h:
     148        (JSC::JITMathIC::JITMathIC):
     149        (JSC::JITMathIC::generateInline):
     150        (JSC::JITMathIC::arithProfile const):
     151        (JSC::JITBinaryMathIC::JITBinaryMathIC):
     152        (JSC::JITUnaryMathIC::JITUnaryMathIC):
     153        * jit/JITMulGenerator.cpp:
     154        (JSC::JITMulGenerator::generateInline):
     155        (JSC::JITMulGenerator::generateFastPath):
     156        * jit/JITMulGenerator.h:
     157        * jit/JITNegGenerator.cpp:
     158        (JSC::JITNegGenerator::generateInline):
     159        (JSC::JITNegGenerator::generateFastPath):
     160        * jit/JITNegGenerator.h:
     161        * jit/JITOperations.cpp:
     162        * jit/JITOperations.h:
     163        * jit/JITSubGenerator.cpp:
     164        (JSC::JITSubGenerator::generateInline):
     165        (JSC::JITSubGenerator::generateFastPath):
     166        * jit/JITSubGenerator.h:
     167        * llint/LLIntData.cpp:
     168        (JSC::LLInt::Data::performAssertions):
     169        * llint/LLIntOffsetsExtractor.cpp:
     170        (JSC::LLIntOffsetsExtractor::dummy):
     171        * llint/LowLevelInterpreter.asm:
     172        * llint/LowLevelInterpreter32_64.asm:
     173        * llint/LowLevelInterpreter64.asm:
     174        * offlineasm/arm.rb:
     175        * offlineasm/arm64.rb:
     176        * offlineasm/cloop.rb:
     177        * offlineasm/instructions.rb:
     178        * offlineasm/mips.rb:
     179        * offlineasm/risc.rb:
     180        * offlineasm/x86.rb:
     181        * parser/ResultType.h:
     182        (JSC::ResultType::ResultType):
     183        * runtime/CommonSlowPaths.cpp:
     184        (JSC::updateArithProfileForUnaryArithOp):
     185        (JSC::updateArithProfileForBinaryArithOp):
     186        (JSC::SLOW_PATH_DECL):
     187
    11882019-11-13  Yusuke Suzuki  <ysuzuki@apple.com>
    2189
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r250654 r252422  
    616616    }
    617617
     618    void or16(TrustedImm32 imm, AbsoluteAddress address)
     619    {
     620        LogicalImmediate logicalImm = LogicalImmediate::create32(imm.m_value);
     621        if (logicalImm.isValid()) {
     622            load16(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate());
     623            m_assembler.orr<32>(dataTempRegister, dataTempRegister, logicalImm);
     624            store16(dataTempRegister, address.m_ptr);
     625        } else {
     626            load16(address.m_ptr, getCachedMemoryTempRegisterIDAndInvalidate());
     627            or32(imm, memoryTempRegister, getCachedDataTempRegisterIDAndInvalidate());
     628            store16(dataTempRegister, address.m_ptr);
     629        }
     630    }
     631
    618632    void or32(RegisterID src, RegisterID dest)
    619633    {
     
    12391253    }
    12401254
     1255    void load16(const void* address, RegisterID dest)
     1256    {
     1257        load<16>(address, dest);
     1258    }
     1259
    12411260    void load16Unaligned(ImplicitAddress address, RegisterID dest)
    12421261    {
     
    15451564        m_assembler.add<64>(memoryTempRegister, memoryTempRegister, address.index, Assembler::UXTX, address.scale);
    15461565        m_assembler.strh(src, address.base, memoryTempRegister);
     1566    }
     1567
     1568    void store16(RegisterID src, const void* address)
     1569    {
     1570        store<16>(src, address);
     1571    }
     1572
     1573    void store16(TrustedImm32 imm, const void* address)
     1574    {
     1575        if (!imm.m_value) {
     1576            store16(ARM64Registers::zr, address);
     1577            return;
     1578        }
     1579
     1580        moveToCachedReg(imm, dataMemoryTempRegister());
     1581        store16(dataTempRegister, address);
    15471582    }
    15481583
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r250005 r252422  
    366366        m_assembler.orr(dest, dest, src);
    367367    }
     368
     369    void or16(TrustedImm32 imm, AbsoluteAddress dest)
     370    {
     371        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
     372        if (armImm.isValid()) {
     373            move(TrustedImmPtr(address.m_ptr), addressTempRegister);
     374            load16(addressTempRegister, dataTempRegister);
     375            m_assembler.orr(dataTempRegister, dataTempRegister, armImm);
     376            store16(dataTempRegister, addressTempRegister);
     377        } else {
     378            move(TrustedImmPtr(address.m_ptr), addressTempRegister);
     379            load16(addressTempRegister, dataTempRegister);
     380            move(imm, addressTempRegister);
     381            m_assembler.orr(dataTempRegister, dataTempRegister, addressTempRegister);
     382            move(TrustedImmPtr(address.m_ptr), addressTempRegister);
     383            store16(dataTempRegister, addressTempRegister);
     384        }
     385    }
    368386   
    369387    void or32(RegisterID src, AbsoluteAddress dest)
     
    783801    }
    784802
     803    void load16(const void* address, RegisterID dest)
     804    {
     805        move(TrustedImmPtr(address), addressTempRegister);
     806        m_assembler.ldrh(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     807    }
     808
    785809    void load16(BaseIndex address, RegisterID dest)
    786810    {
     
    888912    {
    889913        store16(src, setupArmAddress(address));
     914    }
     915
     916    void store16(RegisterID src, const void* address)
     917    {
     918        move(TrustedImmPtr(address), addressTempRegister);
     919        m_assembler.strh(src, addressTempRegister, ARMThumbImmediate::makeUInt12(0));
     920    }
     921
     922    void store16(TrustedImm32 imm, const void* address)
     923    {
     924        move(imm, dataTempRegister);
     925        store16(dataTempRegister, address);
    890926    }
    891927
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h

    r250005 r252422  
    474474    {
    475475        m_assembler.subu(dest, MIPSRegisters::zero, src);
     476    }
     477
     478    void or16(TrustedImm32 imm, AbsoluteAddress dest)
     479    {
     480        if (!imm.m_value && !m_fixedWidth)
     481            return;
     482
     483        if (m_fixedWidth) {
     484            // TODO: Swap dataTempRegister and immTempRegister usage
     485            load16(dest.m_ptr, immTempRegister);
     486            or32(imm, immTempRegister);
     487            store16(immTempRegister, dest.m_ptr);
     488        } else {
     489            uintptr_t adr = reinterpret_cast<uintptr_t>(dest.m_ptr);
     490            m_assembler.lui(addrTempRegister, (adr + 0x8000) >> 16);
     491            m_assembler.lw(immTempRegister, addrTempRegister, adr & 0xffff);
     492            or16(imm, immTempRegister);
     493            m_assembler.sw(immTempRegister, addrTempRegister, adr & 0xffff);
     494        }
    476495    }
    477496
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h

    r250005 r252422  
    100100        m_assembler.orl_rm(reg, address.m_ptr);
    101101    }
     102
     103    void or16(TrustedImm32 imm, AbsoluteAddress address)
     104    {
     105        m_assembler.orw_im(imm.m_value, address.m_ptr);
     106    }
    102107   
    103108    void sub32(TrustedImm32 imm, AbsoluteAddress address)
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h

    r250559 r252422  
    4848    using MacroAssemblerX86Common::branchAdd32;
    4949    using MacroAssemblerX86Common::or32;
     50    using MacroAssemblerX86Common::or16;
    5051    using MacroAssemblerX86Common::sub32;
    5152    using MacroAssemblerX86Common::load8;
     
    8889        move(TrustedImmPtr(address.m_ptr), scratchRegister());
    8990        or32(reg, Address(scratchRegister()));
     91    }
     92
     93    void or16(TrustedImm32 imm, AbsoluteAddress address)
     94    {
     95        move(TrustedImmPtr(address.m_ptr), scratchRegister());
     96        or16(imm, Address(scratchRegister()));
    9097    }
    9198
  • trunk/Source/JavaScriptCore/assembler/testmasm.cpp

    r250695 r252422  
    11051105#endif // ENABLE(MASM_PROBE)
    11061106
     1107void testOrImmMem()
     1108{
     1109    // FIXME: this does not test that the or does not touch beyond its width.
     1110    // I am not sure how to do such a test without a lot of complexity (running multiple threads, with a race on the high bits of the memory location).
     1111    uint64_t memoryLocation = 0x12341234;
     1112    auto or32 = compile([&] (CCallHelpers& jit) {
     1113        emitFunctionPrologue(jit);
     1114        jit.or32(CCallHelpers::TrustedImm32(42), CCallHelpers::AbsoluteAddress(&memoryLocation));
     1115        emitFunctionEpilogue(jit);
     1116        jit.ret();
     1117    });
     1118    invoke<void>(or32);
     1119    CHECK_EQ(memoryLocation, 0x12341234 | 42);
     1120
     1121    memoryLocation = 0x12341234;
     1122    auto or16 = compile([&] (CCallHelpers& jit) {
     1123        emitFunctionPrologue(jit);
     1124        jit.or16(CCallHelpers::TrustedImm32(42), CCallHelpers::AbsoluteAddress(&memoryLocation));
     1125        emitFunctionEpilogue(jit);
     1126        jit.ret();
     1127    });
     1128    invoke<void>(or16);
     1129    CHECK_EQ(memoryLocation, 0x12341234 | 42);
     1130}
     1131
    11071132void testByteSwap()
    11081133{
     
    13611386    RUN(testCagePreservesPACFailureBit());
    13621387
     1388    RUN(testOrImmMem());
     1389
    13631390    if (tasks.isEmpty())
    13641391        usage();
  • trunk/Source/JavaScriptCore/bytecode/ArithProfile.cpp

    r252273 r252422  
    3333
    3434#if ENABLE(JIT)
    35 void ArithProfile::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
     35template<typename BitfieldType>
     36void ArithProfile<BitfieldType>::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
    3637{
    3738    if (!shouldEmitSetDouble() && !shouldEmitSetNonNumeric() && !shouldEmitSetBigInt())
     
    5960}
    6061
    61 bool ArithProfile::shouldEmitSetDouble() const
    62 {
    63     uint32_t mask = ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble;
     62template<typename BitfieldType>
     63bool ArithProfile<BitfieldType>::shouldEmitSetDouble() const
     64{
     65    BitfieldType mask = Int32Overflow | Int52Overflow | NegZeroDouble | NonNegZeroDouble;
    6466    return (m_bits & mask) != mask;
    6567}
    6668
    67 void ArithProfile::emitSetDouble(CCallHelpers& jit) const
     69template<typename BitfieldType>
     70void ArithProfile<BitfieldType>::emitSetDouble(CCallHelpers& jit) const
    6871{
    6972    if (shouldEmitSetDouble())
    70         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits()));
    71 }
    72 
    73 bool ArithProfile::shouldEmitSetNonNumeric() const
    74 {
    75     uint32_t mask = ArithProfile::NonNumeric;
     73        emitUnconditionalSet(jit, Int32Overflow | Int52Overflow | NegZeroDouble | NonNegZeroDouble);
     74}
     75
     76template<typename BitfieldType>
     77bool ArithProfile<BitfieldType>::shouldEmitSetNonNumeric() const
     78{
     79    BitfieldType mask = ArithProfile::NonNumeric;
    7680    return (m_bits & mask) != mask;
    7781}
    7882
    79 bool ArithProfile::shouldEmitSetBigInt() const
    80 {
    81     uint32_t mask = ArithProfile::BigInt;
     83template<typename BitfieldType>
     84void ArithProfile<BitfieldType>::emitSetNonNumeric(CCallHelpers& jit) const
     85{
     86    if (shouldEmitSetNonNumeric())
     87        emitUnconditionalSet(jit, NonNumeric);
     88}
     89
     90template<typename BitfieldType>
     91bool ArithProfile<BitfieldType>::shouldEmitSetBigInt() const
     92{
     93    BitfieldType mask = ArithProfile::BigInt;
    8294    return (m_bits & mask) != mask;
    8395}
    8496
    85 void ArithProfile::emitSetNonNumeric(CCallHelpers& jit) const
    86 {
    87     if (shouldEmitSetNonNumeric())
    88         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumeric), CCallHelpers::AbsoluteAddress(addressOfBits()));
    89 }
    90 
    91 void ArithProfile::emitSetBigInt(CCallHelpers& jit) const
     97template<typename BitfieldType>
     98void ArithProfile<BitfieldType>::emitSetBigInt(CCallHelpers& jit) const
    9299{
    93100    if (shouldEmitSetBigInt())
    94         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::BigInt), CCallHelpers::AbsoluteAddress(addressOfBits()));
    95 }
     101        emitUnconditionalSet(jit, BigInt);
     102}
     103
     104template<typename BitfieldType>
     105void ArithProfile<BitfieldType>::emitUnconditionalSet(CCallHelpers& jit, BitfieldType mask) const
     106{
     107    static_assert(std::is_same<BitfieldType, uint16_t>::value);
     108    jit.or16(CCallHelpers::TrustedImm32(mask), CCallHelpers::AbsoluteAddress(addressOfBits()));
     109}
     110
     111// Generate the implementations of the functions above for UnaryArithProfile/BinaryArithProfile
     112// If changing the size of either, add the corresponding lines here.
     113template class ArithProfile<uint16_t>;
    96114#endif // ENABLE(JIT)
    97115
     
    102120using namespace JSC;
    103121
    104 void printInternal(PrintStream& out, const ArithProfile& profile)
     122template <typename T>
     123void printInternal(PrintStream& out, const ArithProfile<T>& profile)
    105124{
    106125    const char* separator = "";
     
    136155        }
    137156    }
     157    out.print(">");
     158}
     159
     160void printInternal(PrintStream& out, const UnaryArithProfile& profile)
     161{
     162    printInternal(out, static_cast<ArithProfile<UnaryArithProfileBase>>(profile));
     163
     164    out.print(" Arg ObservedType:<");
     165    out.print(profile.argObservedType());
     166    out.print(">");
     167}
     168
     169void printInternal(PrintStream& out, const BinaryArithProfile& profile)
     170{
     171    printInternal(out, static_cast<ArithProfile<UnaryArithProfileBase>>(profile));
     172
    138173    if (profile.tookSpecialFastPath())
    139         out.print(separator, "Took special fast path.");
    140     out.print(">");
     174        out.print(" Took special fast path.");
    141175
    142176    out.print(" LHS ObservedType:<");
     
    145179    out.print(profile.rhsObservedType());
    146180    out.print(">");
    147 
    148     out.print(" LHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.lhsResultType().bits()))));
    149     out.print("> RHS ResultType:<", RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(profile.rhsResultType().bits()))));
    150     out.print(">");
    151181}
    152182
  • trunk/Source/JavaScriptCore/bytecode/ArithProfile.h

    r252273 r252422  
    6767};
    6868
    69 struct ArithProfile {
    70 private:
    71     static constexpr uint32_t numberOfFlagBits = 6;
    72     static constexpr uint32_t rhsResultTypeShift = numberOfFlagBits;
    73     static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
    74     static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
    75     static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
    76 
    77     static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
    78     static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2))));
    79     static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2))));
    80 
    81     static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
    82     static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
    83 
    84     enum class ConstantTag { Constant };
    85 
     69template <typename BitfieldType>
     70class ArithProfile {
    8671public:
    87     static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
    88     static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) <= (sizeof(uint32_t) * 8) - 1, "Should fit in a uint32_t.");
    89     static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
    90     static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
    91     static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
    92 
    93     ArithProfile(ResultType arg)
    94         : ArithProfile(ConstantTag::Constant, arg)
    95     {
    96         ASSERT(lhsResultType().bits() == arg.bits());
    97         ASSERT(lhsObservedType().isEmpty());
    98         ASSERT(rhsObservedType().isEmpty());
    99     }
    100 
    101     ArithProfile(ResultType lhs, ResultType rhs)
    102         : ArithProfile(ConstantTag::Constant, lhs, rhs)
    103     {
    104         ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());
    105         ASSERT(lhsObservedType().isEmpty());
    106         ASSERT(rhsObservedType().isEmpty());
    107     }
    108 
    109     ArithProfile(OperandTypes types)
    110         : ArithProfile(types.first(), types.second())
    111     { }
    112 
    113     ArithProfile() = default;
    114 
    115     static constexpr ArithProfile fromInt(uint32_t bits)
    116     {
    117         return ArithProfile { ConstantTag::Constant, bits };
    118     }
    119 
    120     static constexpr ArithProfile observedUnaryInt()
    121     {
    122         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    123         constexpr uint32_t bits = observedInt32.bits() << lhsObservedTypeShift;
    124         static_assert(bits == 0x800000, "");
    125         return fromInt(bits);
    126     }
    127     static constexpr ArithProfile observedUnaryNumber()
    128     {
    129         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    130         constexpr uint32_t bits = observedNumber.bits() << lhsObservedTypeShift;
    131         static_assert(bits == 0x1000000, "");
    132         return fromInt(bits);
    133     }
    134     static constexpr ArithProfile observedBinaryIntInt()
    135     {
    136         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    137         constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    138         static_assert(bits == 0x900000, "");
    139         return fromInt(bits);
    140     }
    141     static constexpr ArithProfile observedBinaryNumberInt()
    142     {
    143         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    144         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    145         constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
    146         static_assert(bits == 0x1100000, "");
    147         return fromInt(bits);
    148     }
    149     static constexpr ArithProfile observedBinaryIntNumber()
    150     {
    151         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    152         constexpr ObservedType observedInt32 { ObservedType().withInt32() };
    153         constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    154         static_assert(bits == 0xa00000, "");
    155         return fromInt(bits);
    156     }
    157     static constexpr ArithProfile observedBinaryNumberNumber()
    158     {
    159         constexpr ObservedType observedNumber { ObservedType().withNumber() };
    160         constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
    161         static_assert(bits == 0x1200000, "");
    162         return fromInt(bits);
    163     }
    164 
    165     enum ObservedResults {
     72    enum ObservedResults : BitfieldType {
    16673        NonNegZeroDouble = 1 << 0,
    16774        NegZeroDouble    = 1 << 1,
     
    17178        BigInt           = 1 << 5,
    17279    };
    173 
    174     ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); }
    175     ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); }
    176 
    177     constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
    178     constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
    179     void setLhsObservedType(ObservedType type)
    180     {
    181         uint32_t bits = m_bits;
    182         bits &= clearLhsObservedTypeBitMask;
    183         bits |= type.bits() << lhsObservedTypeShift;
    184         m_bits = bits;
    185         ASSERT(lhsObservedType() == type);
    186     }
    187 
    188     void setRhsObservedType(ObservedType type)
    189     {
    190         uint32_t bits = m_bits;
    191         bits &= clearRhsObservedTypeBitMask;
    192         bits |= type.bits() << rhsObservedTypeShift;
    193         m_bits = bits;
    194         ASSERT(rhsObservedType() == type);
    195     }
    196 
    197     bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
     80    static constexpr uint32_t observedResultsNumBitsNeeded = 6;
    19881
    19982    bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); }
     
    21295    void setObservedInt32Overflow() { setBit(Int32Overflow); }
    21396    void setObservedInt52Overflow() { setBit(Int52Overflow); }
    214 
    215     const void* addressOfBits() const { return &m_bits; }
    21697
    21798    void observeResult(JSValue value)
     
    230111    }
    231112
     113    const void* addressOfBits() const { return &m_bits; }
     114
     115#if ENABLE(JIT)
     116    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
     117    // double. Sets NonNumeric if it sees a non-numeric.
     118    void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
     119
     120    // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
     121    bool shouldEmitSetDouble() const;
     122    void emitSetDouble(CCallHelpers&) const;
     123
     124    // Sets NonNumeric
     125    void emitSetNonNumeric(CCallHelpers&) const;
     126    bool shouldEmitSetNonNumeric() const;
     127
     128    // Sets BigInt
     129    void emitSetBigInt(CCallHelpers&) const;
     130    bool shouldEmitSetBigInt() const;
     131
     132    void emitUnconditionalSet(CCallHelpers&, BitfieldType) const;
     133#endif // ENABLE(JIT)
     134
     135    constexpr uint32_t bits() const { return m_bits; }
     136
     137protected:
     138    ArithProfile()
     139    {
     140    }
     141
     142    bool hasBits(int mask) const { return m_bits & mask; }
     143    void setBit(int mask) { m_bits |= mask; }
     144
     145    BitfieldType m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
     146};
     147
     148/* This class stores the following components in 16 bits:
     149 * - ObservedResults
     150 * - ObservedType for the argument
     151 */
     152using UnaryArithProfileBase = uint16_t;
     153class UnaryArithProfile : public ArithProfile<UnaryArithProfileBase> {
     154    static constexpr unsigned argObservedTypeShift = observedResultsNumBitsNeeded;
     155
     156    static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(UnaryArithProfileBase) * 8, "Should fit in a the type of the underlying bitfield.");
     157
     158    static constexpr UnaryArithProfileBase clearArgObservedTypeBitMask = static_cast<UnaryArithProfileBase>(~(0b111 << argObservedTypeShift));
     159
     160    static constexpr UnaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
     161
     162public:
     163    UnaryArithProfile()
     164        : ArithProfile<UnaryArithProfileBase>()
     165    {
     166        ASSERT(argObservedType().isEmpty());
     167        ASSERT(argObservedType().isEmpty());
     168    }
     169
     170    static constexpr UnaryArithProfileBase observedIntBits()
     171    {
     172        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     173        constexpr UnaryArithProfileBase bits = observedInt32.bits() << argObservedTypeShift;
     174        return bits;
     175    }
     176    static constexpr UnaryArithProfileBase observedNumberBits()
     177    {
     178        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     179        constexpr UnaryArithProfileBase bits = observedNumber.bits() << argObservedTypeShift;
     180        return bits;
     181    }
     182
     183    constexpr ObservedType argObservedType() const { return ObservedType((m_bits >> argObservedTypeShift) & observedTypeMask); }
     184    void setArgObservedType(ObservedType type)
     185    {
     186        UnaryArithProfileBase bits = m_bits;
     187        bits &= clearArgObservedTypeBitMask;
     188        bits |= type.bits() << argObservedTypeShift;
     189        m_bits = bits;
     190        ASSERT(argObservedType() == type);
     191    }
     192
     193    void argSawInt32() { setArgObservedType(argObservedType().withInt32()); }
     194    void argSawNumber() { setArgObservedType(argObservedType().withNumber()); }
     195    void argSawNonNumber() { setArgObservedType(argObservedType().withNonNumber()); }
     196
     197    void observeArg(JSValue arg)
     198    {
     199        UnaryArithProfile newProfile = *this;
     200        if (arg.isNumber()) {
     201            if (arg.isInt32())
     202                newProfile.argSawInt32();
     203            else
     204                newProfile.argSawNumber();
     205        } else
     206            newProfile.argSawNonNumber();
     207
     208        m_bits = newProfile.bits();
     209    }
     210
     211    bool isObservedTypeEmpty()
     212    {
     213        return argObservedType().isEmpty();
     214    }
     215
     216    friend class JSC::LLIntOffsetsExtractor;
     217};
     218
     219/* This class stores the following components in 16 bits:
     220 * - ObservedResults
     221 * - ObservedType for right-hand-side
     222 * - ObservedType for left-hand-side
     223 * - a bit used by division to indicate whether a special fast path was taken
     224 */
     225using BinaryArithProfileBase = uint16_t;
     226class BinaryArithProfile : public ArithProfile<BinaryArithProfileBase> {
     227    static constexpr uint32_t rhsObservedTypeShift = observedResultsNumBitsNeeded;
     228    static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
     229
     230    static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
     231    static constexpr BinaryArithProfileBase clearRhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << rhsObservedTypeShift));
     232    static constexpr BinaryArithProfileBase clearLhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << lhsObservedTypeShift));
     233
     234    static constexpr BinaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
     235
     236public:
     237    static constexpr BinaryArithProfileBase specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
     238    static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(BinaryArithProfileBase) * 8, "Should fit in a uint32_t.");
     239    static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
     240    static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
     241    static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
     242
     243    BinaryArithProfile()
     244        : ArithProfile<BinaryArithProfileBase> ()
     245    {
     246        ASSERT(lhsObservedType().isEmpty());
     247        ASSERT(rhsObservedType().isEmpty());
     248    }
     249
     250    static constexpr BinaryArithProfileBase observedIntIntBits()
     251    {
     252        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     253        constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
     254        return bits;
     255    }
     256    static constexpr BinaryArithProfileBase observedNumberIntBits()
     257    {
     258        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     259        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     260        constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
     261        return bits;
     262    }
     263    static constexpr BinaryArithProfileBase observedIntNumberBits()
     264    {
     265        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     266        constexpr ObservedType observedInt32 { ObservedType().withInt32() };
     267        constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
     268        return bits;
     269    }
     270    static constexpr BinaryArithProfileBase observedNumberNumberBits()
     271    {
     272        constexpr ObservedType observedNumber { ObservedType().withNumber() };
     273        constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
     274        return bits;
     275    }
     276
     277    constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
     278    constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
     279    void setLhsObservedType(ObservedType type)
     280    {
     281        BinaryArithProfileBase bits = m_bits;
     282        bits &= clearLhsObservedTypeBitMask;
     283        bits |= type.bits() << lhsObservedTypeShift;
     284        m_bits = bits;
     285        ASSERT(lhsObservedType() == type);
     286    }
     287
     288    void setRhsObservedType(ObservedType type)
     289    {
     290        BinaryArithProfileBase bits = m_bits;
     291        bits &= clearRhsObservedTypeBitMask;
     292        bits |= type.bits() << rhsObservedTypeShift;
     293        m_bits = bits;
     294        ASSERT(rhsObservedType() == type);
     295    }
     296
     297    bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }
     298
    232299    void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); }
    233300    void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); }
     
    239306    void observeLHS(JSValue lhs)
    240307    {
    241         ArithProfile newProfile = *this;
     308        BinaryArithProfile newProfile = *this;
    242309        if (lhs.isNumber()) {
    243310            if (lhs.isInt32())
     
    255322        observeLHS(lhs);
    256323
    257         ArithProfile newProfile = *this;
     324        BinaryArithProfile newProfile = *this;
    258325        if (rhs.isNumber()) {
    259326            if (rhs.isInt32())
     
    267334    }
    268335
    269 #if ENABLE(JIT)   
    270     // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
    271     // double. Sets NonNumeric if it sees a non-numeric.
    272     void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
    273    
    274     // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
    275     bool shouldEmitSetDouble() const;
    276     void emitSetDouble(CCallHelpers&) const;
    277    
    278     // Sets NonNumber.
    279     void emitSetNonNumeric(CCallHelpers&) const;
    280     bool shouldEmitSetNonNumeric() const;
    281 
    282     // Sets BigInt
    283     void emitSetBigInt(CCallHelpers&) const;
    284     bool shouldEmitSetBigInt() const;
    285 #endif // ENABLE(JIT)
    286 
    287     constexpr uint32_t bits() const { return m_bits; }
    288 
    289 private:
    290     constexpr explicit ArithProfile(ConstantTag, uint32_t bits)
    291         : m_bits(bits)
    292     {
    293     }
    294 
    295     constexpr ArithProfile(ConstantTag, ResultType arg)
    296         : m_bits(arg.bits() << lhsResultTypeShift)
    297     {
    298     }
    299 
    300     constexpr ArithProfile(ConstantTag, ResultType lhs, ResultType rhs)
    301         : m_bits((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift))
    302     {
    303     }
    304 
    305     bool hasBits(int mask) const { return m_bits & mask; }
    306     void setBit(int mask) { m_bits |= mask; }
    307 
    308     uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it.
     336    bool isObservedTypeEmpty()
     337    {
     338        return lhsObservedType().isEmpty() && rhsObservedType().isEmpty();
     339    }
    309340
    310341    friend class JSC::LLIntOffsetsExtractor;
     
    315346namespace WTF {
    316347
    317 void printInternal(PrintStream&, const JSC::ArithProfile&);
     348void printInternal(PrintStream&, const JSC::UnaryArithProfile&);
     349void printInternal(PrintStream&, const JSC::BinaryArithProfile&);
    318350void printInternal(PrintStream&, const JSC::ObservedType&);
    319351
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r252273 r252422  
    4242    :JSValue,
    4343    :LLIntCallLinkInfo,
     44    :ResultType,
    4445    :OperandTypes,
    4546    :ProfileTypeBytecodeFlag,
     
    5960    :ValueProfile,
    6061    :ValueProfileAndOperandBuffer,
    61     :ArithProfile,
     62    :UnaryArithProfile,
     63    :BinaryArithProfile,
    6264    :ArrayProfile,
    6365    :ArrayAllocationProfile,
     
    280282    },
    281283    metadata: {
    282         arithProfile: ArithProfile
    283     },
    284     metadata_initializers: {
    285         arithProfile: :operandTypes
     284        arithProfile: BinaryArithProfile
    286285    }
    287286
     
    365364        dst: VirtualRegister,
    366365        operand: VirtualRegister,
    367         operandTypes: OperandTypes,
    368     },
    369     metadata: {
    370         arithProfile: ArithProfile,
    371     },
    372     metadata_initializers: {
    373         arithProfile: :operandTypes
     366        resultType: ResultType,
     367    },
     368    metadata: {
     369        arithProfile: UnaryArithProfile,
    374370    }
    375371
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r252273 r252422  
    14801480}
    14811481
    1482 JITAddIC* CodeBlock::addJITAddIC(ArithProfile* arithProfile)
     1482JITAddIC* CodeBlock::addJITAddIC(BinaryArithProfile* arithProfile)
    14831483{
    14841484    ConcurrentJSLocker locker(m_lock);
     
    14861486}
    14871487
    1488 JITMulIC* CodeBlock::addJITMulIC(ArithProfile* arithProfile)
     1488JITMulIC* CodeBlock::addJITMulIC(BinaryArithProfile* arithProfile)
    14891489{
    14901490    ConcurrentJSLocker locker(m_lock);
     
    14921492}
    14931493
    1494 JITSubIC* CodeBlock::addJITSubIC(ArithProfile* arithProfile)
     1494JITSubIC* CodeBlock::addJITSubIC(BinaryArithProfile* arithProfile)
    14951495{
    14961496    ConcurrentJSLocker locker(m_lock);
     
    14981498}
    14991499
    1500 JITNegIC* CodeBlock::addJITNegIC(ArithProfile* arithProfile)
     1500JITNegIC* CodeBlock::addJITNegIC(UnaryArithProfile* arithProfile)
    15011501{
    15021502    ConcurrentJSLocker locker(m_lock);
     
    30853085}
    30863086
    3087 ArithProfile* CodeBlock::arithProfileForBytecodeIndex(BytecodeIndex bytecodeIndex)
    3088 {
    3089     return arithProfileForPC(instructions().at(bytecodeIndex.offset()).ptr());
    3090 }
    3091 
    3092 ArithProfile* CodeBlock::arithProfileForPC(const Instruction* pc)
     3087BinaryArithProfile* CodeBlock::binaryArithProfileForBytecodeIndex(BytecodeIndex bytecodeIndex)
     3088{
     3089    return binaryArithProfileForPC(instructions().at(bytecodeIndex.offset()).ptr());
     3090}
     3091
     3092UnaryArithProfile* CodeBlock::unaryArithProfileForBytecodeIndex(BytecodeIndex bytecodeIndex)
     3093{
     3094    return unaryArithProfileForPC(instructions().at(bytecodeIndex.offset()).ptr());
     3095}
     3096
     3097BinaryArithProfile* CodeBlock::binaryArithProfileForPC(const Instruction* pc)
    30933098{
    30943099    switch (pc->opcodeID()) {
    3095     case op_negate:
    3096         return &pc->as<OpNegate>().metadata(this).m_arithProfile;
    30973100    case op_add:
    30983101        return &pc->as<OpAdd>().metadata(this).m_arithProfile;
     
    31103113}
    31113114
     3115UnaryArithProfile* CodeBlock::unaryArithProfileForPC(const Instruction* pc)
     3116{
     3117    switch (pc->opcodeID()) {
     3118    case op_negate:
     3119        return &pc->as<OpNegate>().metadata(this).m_arithProfile;
     3120    default:
     3121        break;
     3122    }
     3123
     3124    return nullptr;
     3125}
     3126
    31123127bool CodeBlock::couldTakeSpecialArithFastCase(BytecodeIndex bytecodeIndex)
    31133128{
    31143129    if (!hasBaselineJITProfiling())
    31153130        return false;
    3116     ArithProfile* profile = arithProfileForBytecodeIndex(bytecodeIndex);
     3131    BinaryArithProfile* profile = binaryArithProfileForBytecodeIndex(bytecodeIndex);
    31173132    if (!profile)
    31183133        return false;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r252385 r252422  
    8484#endif
    8585
     86class UnaryArithProfile;
     87class BinaryArithProfile;
    8688class BytecodeLivenessAnalysis;
    8789class CodeBlockSet;
     
    9799enum class AccessType : int8_t;
    98100
    99 struct ArithProfile;
    100101struct OpCatch;
    101102
     
    282283    JITData& ensureJITDataSlow(const ConcurrentJSLocker&);
    283284
    284     JITAddIC* addJITAddIC(ArithProfile*);
    285     JITMulIC* addJITMulIC(ArithProfile*);
    286     JITNegIC* addJITNegIC(ArithProfile*);
    287     JITSubIC* addJITSubIC(ArithProfile*);
     285    JITAddIC* addJITAddIC(BinaryArithProfile*);
     286    JITMulIC* addJITMulIC(BinaryArithProfile*);
     287    JITNegIC* addJITNegIC(UnaryArithProfile*);
     288    JITSubIC* addJITSubIC(BinaryArithProfile*);
    288289
    289290    template <typename Generator, typename = typename std::enable_if<std::is_same<Generator, JITAddGenerator>::value>::type>
    290     JITAddIC* addMathIC(ArithProfile* profile) { return addJITAddIC(profile); }
     291    JITAddIC* addMathIC(BinaryArithProfile* profile) { return addJITAddIC(profile); }
    291292
    292293    template <typename Generator, typename = typename std::enable_if<std::is_same<Generator, JITMulGenerator>::value>::type>
    293     JITMulIC* addMathIC(ArithProfile* profile) { return addJITMulIC(profile); }
     294    JITMulIC* addMathIC(BinaryArithProfile* profile) { return addJITMulIC(profile); }
    294295
    295296    template <typename Generator, typename = typename std::enable_if<std::is_same<Generator, JITNegGenerator>::value>::type>
    296     JITNegIC* addMathIC(ArithProfile* profile) { return addJITNegIC(profile); }
     297    JITNegIC* addMathIC(UnaryArithProfile* profile) { return addJITNegIC(profile); }
    297298
    298299    template <typename Generator, typename = typename std::enable_if<std::is_same<Generator, JITSubGenerator>::value>::type>
    299     JITSubIC* addMathIC(ArithProfile* profile) { return addJITSubIC(profile); }
     300    JITSubIC* addMathIC(BinaryArithProfile* profile) { return addJITSubIC(profile); }
    300301
    301302    StructureStubInfo* addStubInfo(AccessType);
     
    500501    template<typename Functor> void forEachLLIntCallLinkInfo(const Functor&);
    501502
    502     ArithProfile* arithProfileForBytecodeIndex(BytecodeIndex);
    503     ArithProfile* arithProfileForPC(const Instruction*);
     503    BinaryArithProfile* binaryArithProfileForBytecodeIndex(BytecodeIndex);
     504    UnaryArithProfile* unaryArithProfileForBytecodeIndex(BytecodeIndex);
     505    BinaryArithProfile* binaryArithProfileForPC(const Instruction*);
     506    UnaryArithProfile* unaryArithProfileForPC(const Instruction*);
    504507
    505508    bool couldTakeSpecialArithFastCase(BytecodeIndex bytecodeOffset);
  • trunk/Source/JavaScriptCore/bytecode/Fits.h

    r252273 r252422  
    237237
    238238template<OpcodeSize size>
     239struct Fits<ResultType, size, std::enable_if_t<sizeof(ResultType) != size, std::true_type>> : public Fits<uint8_t, size> {
     240    static_assert(sizeof(ResultType) == sizeof(uint8_t));
     241    using Base = Fits<uint8_t, size>;
     242
     243    static bool check(ResultType type) { return Base::check(type.bits()); }
     244
     245    static typename Base::TargetType convert(ResultType type) { return Base::convert(type.bits()); }
     246
     247    static ResultType convert(typename Base::TargetType type) { return ResultType(Base::convert(type)); }
     248};
     249
     250template<OpcodeSize size>
    239251struct Fits<OperandTypes, size, std::enable_if_t<sizeof(OperandTypes) != size, std::true_type>> {
    240252    static_assert(sizeof(OperandTypes) == sizeof(uint16_t));
  • trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp

    r252273 r252422  
    6767    }
    6868       
    69     case ArithProfileReady: {
    70         u.arithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters);
     69    case UnaryArithProfileReady: {
     70        u.unaryArithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters);
    7171        return;
    72     } }
     72    }
     73
     74    case BinaryArithProfileReady: {
     75        u.binaryArithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters);
     76        return;
     77    }
     78    }
    7379   
    7480    RELEASE_ASSERT_NOT_REACHED();
     
    95101    }
    96102
    97     case ArithProfileReady: {
    98         u.arithProfile->observeResult(value);
     103    case UnaryArithProfileReady: {
     104        u.unaryArithProfile->observeResult(value);
    99105        return;
    100     } }
     106    }
     107
     108    case BinaryArithProfileReady: {
     109        u.binaryArithProfile->observeResult(value);
     110        return;
     111    }
     112    }
    101113
    102114    RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h

    r252273 r252422  
    3737namespace JSC {
    3838
     39class UnaryArithProfile;
     40class BinaryArithProfile;
    3941class CCallHelpers;
    4042class CodeBlock;
    4143class LazyOperandValueProfileKey;
    42 struct ArithProfile;
    4344struct ValueProfile;
    4445
     
    5859            m_kind = None;
    5960    }
    60    
    61     MethodOfGettingAValueProfile(ArithProfile* profile)
     61
     62    MethodOfGettingAValueProfile(UnaryArithProfile* profile)
    6263    {
    6364        if (profile) {
    64             m_kind = ArithProfileReady;
    65             u.arithProfile = profile;
     65            m_kind = UnaryArithProfileReady;
     66            u.unaryArithProfile = profile;
     67        } else
     68            m_kind = None;
     69    }
     70
     71    MethodOfGettingAValueProfile(BinaryArithProfile* profile)
     72    {
     73        if (profile) {
     74            m_kind = BinaryArithProfileReady;
     75            u.binaryArithProfile = profile;
    6676        } else
    6777            m_kind = None;
     
    8090        None,
    8191        Ready,
    82         ArithProfileReady,
     92        UnaryArithProfileReady,
     93        BinaryArithProfileReady,
    8394        LazyOperand
    8495    };
     
    91102
    92103        ValueProfile* profile;
    93         ArithProfile* arithProfile;
     104        UnaryArithProfile* unaryArithProfile;
     105        BinaryArithProfile* binaryArithProfile;
    94106        struct {
    95107            CodeBlock* codeBlock;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r252273 r252422  
    15171517}
    15181518
    1519 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, OperandTypes types)
     1519RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, ResultType type)
    15201520{
    15211521    switch (opcodeID) {
     
    15241524        break;
    15251525    case op_negate:
    1526         OpNegate::emit(this, dst, src, types);
     1526        OpNegate::emit(this, dst, src, type);
    15271527        break;
    15281528    case op_bitnot:
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r252306 r252422  
    683683        }
    684684
    685         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, OperandTypes);
     685        RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, ResultType);
    686686
    687687        template<typename BinaryOp>
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r252273 r252422  
    21472147    RefPtr<RegisterID> src = generator.emitNode(m_expr);
    21482148    generator.emitExpressionInfo(position(), position(), position());
    2149     return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
     2149    return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), m_expr->resultDescriptor());
    21502150}
    21512151
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r252273 r252422  
    943943            return node;
    944944
    945         {
    946             ArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->arithProfileForBytecodeIndex(m_currentIndex);
    947             if (arithProfile) {
    948                 switch (node->op()) {
    949                 case ArithAdd:
    950                 case ArithSub:
    951                 case ValueAdd:
    952                     if (arithProfile->didObserveDouble())
    953                         node->mergeFlags(NodeMayHaveDoubleResult);
    954                     if (arithProfile->didObserveNonNumeric())
    955                         node->mergeFlags(NodeMayHaveNonNumericResult);
    956                     if (arithProfile->didObserveBigInt())
    957                         node->mergeFlags(NodeMayHaveBigIntResult);
    958                     break;
    959 
    960                 case ValueMul:
    961                 case ArithMul: {
    962                     if (arithProfile->didObserveInt52Overflow())
    963                         node->mergeFlags(NodeMayOverflowInt52);
    964                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
    965                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
    966                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
    967                         node->mergeFlags(NodeMayNegZeroInBaseline);
    968                     if (arithProfile->didObserveDouble())
    969                         node->mergeFlags(NodeMayHaveDoubleResult);
    970                     if (arithProfile->didObserveNonNumeric())
    971                         node->mergeFlags(NodeMayHaveNonNumericResult);
    972                     if (arithProfile->didObserveBigInt())
    973                         node->mergeFlags(NodeMayHaveBigIntResult);
    974                     break;
    975                 }
    976                 case ValueNegate:
    977                 case ArithNegate: {
    978                     if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble())
    979                         node->mergeFlags(NodeMayHaveDoubleResult);
    980                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
    981                         node->mergeFlags(NodeMayNegZeroInBaseline);
    982                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
    983                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
    984                     if (arithProfile->didObserveNonNumeric())
    985                         node->mergeFlags(NodeMayHaveNonNumericResult);
    986                     if (arithProfile->didObserveBigInt())
    987                         node->mergeFlags(NodeMayHaveBigIntResult);
    988                     break;
    989                 }
    990 
    991                 default:
    992                     break;
    993                 }
    994             }
     945        switch (node->op()) {
     946        case ArithAdd:
     947        case ArithSub:
     948        case ValueAdd: {
     949            BinaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->binaryArithProfileForBytecodeIndex(m_currentIndex);
     950            if (!arithProfile)
     951                break;
     952            if (arithProfile->didObserveDouble())
     953                node->mergeFlags(NodeMayHaveDoubleResult);
     954            if (arithProfile->didObserveNonNumeric())
     955                node->mergeFlags(NodeMayHaveNonNumericResult);
     956            if (arithProfile->didObserveBigInt())
     957                node->mergeFlags(NodeMayHaveBigIntResult);
     958            break;
     959        }
     960        case ValueMul:
     961        case ArithMul: {
     962            BinaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->binaryArithProfileForBytecodeIndex(m_currentIndex);
     963            if (!arithProfile)
     964                break;
     965            if (arithProfile->didObserveInt52Overflow())
     966                node->mergeFlags(NodeMayOverflowInt52);
     967            if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
     968                node->mergeFlags(NodeMayOverflowInt32InBaseline);
     969            if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
     970                node->mergeFlags(NodeMayNegZeroInBaseline);
     971            if (arithProfile->didObserveDouble())
     972                node->mergeFlags(NodeMayHaveDoubleResult);
     973            if (arithProfile->didObserveNonNumeric())
     974                node->mergeFlags(NodeMayHaveNonNumericResult);
     975            if (arithProfile->didObserveBigInt())
     976                node->mergeFlags(NodeMayHaveBigIntResult);
     977            break;
     978        }
     979        case ValueNegate:
     980        case ArithNegate: {
     981            UnaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->unaryArithProfileForBytecodeIndex(m_currentIndex);
     982            if (!arithProfile)
     983                break;
     984            if (arithProfile->argObservedType().sawNumber() || arithProfile->didObserveDouble())
     985                node->mergeFlags(NodeMayHaveDoubleResult);
     986            if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
     987                node->mergeFlags(NodeMayNegZeroInBaseline);
     988            if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
     989                node->mergeFlags(NodeMayOverflowInt32InBaseline);
     990            if (arithProfile->didObserveNonNumeric())
     991                node->mergeFlags(NodeMayHaveNonNumericResult);
     992            if (arithProfile->didObserveBigInt())
     993                node->mergeFlags(NodeMayHaveBigIntResult);
     994            break;
     995        }
     996
     997        default:
     998            break;
    995999        }
    9961000       
     
    10341038        // FIXME: It might be possible to make this more granular.
    10351039        node->mergeFlags(NodeMayOverflowInt32InBaseline | NodeMayNegZeroInBaseline);
    1036        
    1037         ArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->arithProfileForBytecodeIndex(m_currentIndex);
     1040
     1041        BinaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->binaryArithProfileForBytecodeIndex(m_currentIndex);
    10381042        if (arithProfile->didObserveBigInt())
    10391043            node->mergeFlags(NodeMayHaveBigIntResult);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r252273 r252422  
    16551655
    16561656            if (profiledBlock->hasBaselineJITProfiling()) {
    1657                 if (ArithProfile* result = profiledBlock->arithProfileForBytecodeIndex(node->origin.semantic.bytecodeIndex()))
     1657                if (BinaryArithProfile* result = profiledBlock->binaryArithProfileForBytecodeIndex(node->origin.semantic.bytecodeIndex()))
     1658                    return result;
     1659                if (UnaryArithProfile* result = profiledBlock->unaryArithProfileForBytecodeIndex(node->origin.semantic.bytecodeIndex()))
    16581660                    return result;
    16591661            }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r252273 r252422  
    39963996    CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
    39973997    BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
    3998     ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     3998    BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    39993999    JITAddIC* addIC = m_jit.codeBlock()->addJITAddIC(arithProfile);
    40004000    auto repatchingFunction = operationValueAddOptimize;
     
    40204020        CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
    40214021        BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
    4022         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     4022        BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    40234023        JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile);
    40244024        auto repatchingFunction = operationValueSubOptimize;
     
    46144614    CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
    46154615    BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
    4616     ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     4616    UnaryArithProfile* arithProfile = baselineCodeBlock->unaryArithProfileForBytecodeIndex(bytecodeIndex);
    46174617    JITNegIC* negIC = m_jit.codeBlock()->addJITNegIC(arithProfile);
    46184618    auto repatchingFunction = operationArithNegateOptimize;
     
    48374837    CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
    48384838    BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
    4839     ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     4839    BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    48404840    JITMulIC* mulIC = m_jit.codeBlock()->addJITMulIC(arithProfile);
    48414841    auto repatchingFunction = operationValueMulOptimize;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r252273 r252422  
    21172117        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
    21182118        BytecodeIndex bytecodeIndex = m_node->origin.semantic.bytecodeIndex();
    2119         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     2119        BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    21202120        auto repatchingFunction = operationValueAddOptimize;
    21212121        auto nonRepatchingFunction = operationValueAdd;
     
    21382138        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
    21392139        BytecodeIndex bytecodeIndex = m_node->origin.semantic.bytecodeIndex();
    2140         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     2140        BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    21412141        auto repatchingFunction = operationValueSubOptimize;
    21422142        auto nonRepatchingFunction = operationValueSub;
     
    21592159        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
    21602160        BytecodeIndex bytecodeIndex = m_node->origin.semantic.bytecodeIndex();
    2161         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     2161        BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    21622162        auto repatchingFunction = operationValueMulOptimize;
    21632163        auto nonRepatchingFunction = operationValueMul;
     
    21672167    template <typename Generator, typename Func1, typename Func2,
    21682168        typename = std::enable_if_t<std::is_function<typename std::remove_pointer<Func1>::type>::value && std::is_function<typename std::remove_pointer<Func2>::type>::value>>
    2169     void compileUnaryMathIC(ArithProfile* arithProfile, Func1 repatchingFunction, Func2 nonRepatchingFunction)
     2169    void compileUnaryMathIC(UnaryArithProfile* arithProfile, Func1 repatchingFunction, Func2 nonRepatchingFunction)
    21702170    {
    21712171        Node* node = m_node;
     
    22532253    template <typename Generator, typename Func1, typename Func2,
    22542254        typename = std::enable_if_t<std::is_function<typename std::remove_pointer<Func1>::type>::value && std::is_function<typename std::remove_pointer<Func2>::type>::value>>
    2255     void compileBinaryMathIC(ArithProfile* arithProfile, Func1 repatchingFunction, Func2 nonRepatchingFunction)
     2255    void compileBinaryMathIC(BinaryArithProfile* arithProfile, Func1 repatchingFunction, Func2 nonRepatchingFunction)
    22562256    {
    22572257        Node* node = m_node;
     
    24222422            CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
    24232423            BytecodeIndex bytecodeIndex = m_node->origin.semantic.bytecodeIndex();
    2424             ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     2424            BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
    24252425            auto repatchingFunction = operationValueSubOptimize;
    24262426            auto nonRepatchingFunction = operationValueSub;
     
    31003100        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
    31013101        BytecodeIndex bytecodeIndex = m_node->origin.semantic.bytecodeIndex();
    3102         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeIndex(bytecodeIndex);
     3102        UnaryArithProfile* arithProfile = baselineCodeBlock->unaryArithProfileForBytecodeIndex(bytecodeIndex);
    31033103        auto repatchingFunction = operationArithNegateOptimize;
    31043104        auto nonRepatchingFunction = operationArithNegate;
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r252273 r252422  
    920920        GetPutInfo copiedGetPutInfo(OpPutToScope);
    921921        template<typename BinaryOp>
    922         ArithProfile copiedArithProfile(BinaryOp);
     922        BinaryArithProfile copiedArithProfile(BinaryOp);
    923923
    924924        Interpreter* m_interpreter;
     
    940940
    941941        HashMap<unsigned, unsigned> m_copiedGetPutInfos;
    942         HashMap<uint64_t, ArithProfile> m_copiedArithProfiles;
     942        HashMap<uint64_t, BinaryArithProfile> m_copiedArithProfiles;
    943943
    944944        JumpList m_exceptionChecks;
  • trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp

    r252273 r252422  
    3535namespace JSC {
    3636
    37 JITMathICInlineResult JITAddGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const ArithProfile* arithProfile)
     37JITMathICInlineResult JITAddGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const BinaryArithProfile* arithProfile)
    3838{
    3939    // We default to speculating int32.
     
    7474}
    7575
    76 bool JITAddGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling)
     76bool JITAddGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const BinaryArithProfile* arithProfile, bool shouldEmitProfiling)
    7777{
    7878    ASSERT(m_scratchGPR != InvalidGPRReg);
  • trunk/Source/JavaScriptCore/jit/JITAddGenerator.h

    r252273 r252422  
    5656    }
    5757
    58     JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const ArithProfile*);
    59     bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile*, bool shouldEmitProfiling);
     58    JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const BinaryArithProfile*);
     59    bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const BinaryArithProfile*, bool shouldEmitProfiling);
    6060
    6161    static bool isLeftOperandValidConstant(SnippetOperand leftOperand) { return leftOperand.isPositiveConstInt32(); }
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r252273 r252422  
    454454void JIT::emit_op_negate(const Instruction* currentInstruction)
    455455{
    456     ArithProfile* arithProfile = &currentInstruction->as<OpNegate>().metadata(m_codeBlock).m_arithProfile;
     456    UnaryArithProfile* arithProfile = &currentInstruction->as<OpNegate>().metadata(m_codeBlock).m_arithProfile;
    457457    JITNegIC* negateIC = m_codeBlock->addJITNegIC(arithProfile);
    458458    m_instructionToMathIC.add(currentInstruction, negateIC);
     
    635635}
    636636
    637 ALWAYS_INLINE static OperandTypes getOperandTypes(const ArithProfile& arithProfile)
    638 {
    639     return OperandTypes(arithProfile.lhsResultType(), arithProfile.rhsResultType());
    640 }
    641 
    642637void JIT::emit_op_add(const Instruction* currentInstruction)
    643638{
    644     ArithProfile* arithProfile = &currentInstruction->as<OpAdd>().metadata(m_codeBlock).m_arithProfile;
     639    BinaryArithProfile* arithProfile = &currentInstruction->as<OpAdd>().metadata(m_codeBlock).m_arithProfile;
    645640    JITAddIC* addIC = m_codeBlock->addJITAddIC(arithProfile);
    646641    m_instructionToMathIC.add(currentInstruction, addIC);
     
    687682    bool generatedInlineCode = mathIC->generateInline(*this, mathICGenerationState);
    688683    if (!generatedInlineCode) {
    689         ArithProfile* arithProfile = mathIC->arithProfile();
     684        UnaryArithProfile* arithProfile = mathIC->arithProfile();
    690685        if (arithProfile && shouldEmitProfiling())
    691686            callOperationWithResult(profiledFunction, resultRegs, TrustedImmPtr(m_codeBlock->globalObject()), srcRegs, arithProfile);
     
    710705{
    711706    auto bytecode = currentInstruction->as<Op>();
    712     OperandTypes types = getOperandTypes(copiedArithProfile(bytecode));
    713707    int result = bytecode.m_dst.offset();
    714708    int op1 = bytecode.m_lhs.offset();
     
    729723#endif
    730724
    731     SnippetOperand leftOperand(types.first());
    732     SnippetOperand rightOperand(types.second());
     725    SnippetOperand leftOperand(bytecode.m_operandTypes.first());
     726    SnippetOperand rightOperand(bytecode.m_operandTypes.second());
    733727
    734728    if (isOperandConstantInt(op1))
     
    760754        else if (rightOperand.isConst())
    761755            emitGetVirtualRegister(op2, rightRegs);
    762         ArithProfile* arithProfile = mathIC->arithProfile();
     756        BinaryArithProfile* arithProfile = mathIC->arithProfile();
    763757        if (arithProfile && shouldEmitProfiling())
    764758            callOperationWithResult(profiledFunction, resultRegs, TrustedImmPtr(m_codeBlock->globalObject()), leftRegs, rightRegs, arithProfile);
     
    800794#endif
    801795
    802     ArithProfile* arithProfile = mathIC->arithProfile();
     796    UnaryArithProfile* arithProfile = mathIC->arithProfile();
    803797    if (arithProfile && shouldEmitProfiling()) {
    804798        if (mathICGenerationState.shouldSlowPathRepatch)
     
    832826
    833827    auto bytecode = currentInstruction->as<Op>();
    834     OperandTypes types = getOperandTypes(copiedArithProfile(bytecode));
    835828    int result = bytecode.m_dst.offset();
    836829    int op1 = bytecode.m_lhs.offset();
     
    847840#endif
    848841   
    849     SnippetOperand leftOperand(types.first());
    850     SnippetOperand rightOperand(types.second());
     842    SnippetOperand leftOperand(bytecode.m_operandTypes.first());
     843    SnippetOperand rightOperand(bytecode.m_operandTypes.second());
    851844
    852845    if (isOperandConstantInt(op1))
     
    866859#endif
    867860
    868     ArithProfile* arithProfile = mathIC->arithProfile();
     861    BinaryArithProfile* arithProfile = mathIC->arithProfile();
    869862    if (arithProfile && shouldEmitProfiling()) {
    870863        if (mathICGenerationState.shouldSlowPathRepatch)
     
    894887{
    895888    auto bytecode = currentInstruction->as<OpDiv>();
    896     auto& metadata = bytecode.metadata(m_codeBlock);
    897889    int result = bytecode.m_dst.offset();
    898890    int op1 = bytecode.m_lhs.offset();
     
    900892
    901893#if USE(JSVALUE64)
    902     OperandTypes types = getOperandTypes(metadata.m_arithProfile);
    903894    JSValueRegs leftRegs = JSValueRegs(regT0);
    904895    JSValueRegs rightRegs = JSValueRegs(regT1);
     
    906897    GPRReg scratchGPR = regT2;
    907898#else
    908     OperandTypes types = getOperandTypes(metadata.m_arithProfile);
    909899    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
    910900    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
     
    914904    FPRReg scratchFPR = fpRegT2;
    915905
    916     ArithProfile* arithProfile = nullptr;
     906    BinaryArithProfile* arithProfile = nullptr;
    917907    if (shouldEmitProfiling())
    918908        arithProfile = &currentInstruction->as<OpDiv>().metadata(m_codeBlock).m_arithProfile;
    919909
    920     SnippetOperand leftOperand(types.first());
    921     SnippetOperand rightOperand(types.second());
     910    SnippetOperand leftOperand(bytecode.m_operandTypes.first());
     911    SnippetOperand rightOperand(bytecode.m_operandTypes.second());
    922912
    923913    if (isOperandConstantInt(op1))
     
    961951void JIT::emit_op_mul(const Instruction* currentInstruction)
    962952{
    963     ArithProfile* arithProfile = &currentInstruction->as<OpMul>().metadata(m_codeBlock).m_arithProfile;
     953    BinaryArithProfile* arithProfile = &currentInstruction->as<OpMul>().metadata(m_codeBlock).m_arithProfile;
    964954    JITMulIC* mulIC = m_codeBlock->addJITMulIC(arithProfile);
    965955    m_instructionToMathIC.add(currentInstruction, mulIC);
     
    977967void JIT::emit_op_sub(const Instruction* currentInstruction)
    978968{
    979     ArithProfile* arithProfile = &currentInstruction->as<OpSub>().metadata(m_codeBlock).m_arithProfile;
     969    BinaryArithProfile* arithProfile = &currentInstruction->as<OpSub>().metadata(m_codeBlock).m_arithProfile;
    980970    JITSubIC* subIC = m_codeBlock->addJITSubIC(arithProfile);
    981971    m_instructionToMathIC.add(currentInstruction, subIC);
  • trunk/Source/JavaScriptCore/jit/JITDivGenerator.cpp

    r252273 r252422  
    131131#endif
    132132    if (m_arithProfile)
    133         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::specialFastPathBit), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits()));
     133        m_arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::specialFastPathBit);
    134134    jit.boxDouble(m_leftFPR, m_result);
    135135}
  • trunk/Source/JavaScriptCore/jit/JITDivGenerator.h

    r252273 r252422  
    3838        JSValueRegs result, JSValueRegs left, JSValueRegs right,
    3939        FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
    40         ArithProfile* arithProfile = nullptr)
     40        BinaryArithProfile* arithProfile = nullptr)
    4141        : m_leftOperand(leftOperand)
    4242        , m_rightOperand(rightOperand)
     
    7272    FPRReg m_scratchFPR;
    7373    bool m_didEmitFastPath { false };
    74     ArithProfile* m_arithProfile;
     74    BinaryArithProfile* m_arithProfile;
    7575
    7676    CCallHelpers::JumpList m_endJumpList;
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r252273 r252422  
    717717
    718718template<typename BinaryOp>
    719 ALWAYS_INLINE ArithProfile JIT::copiedArithProfile(BinaryOp bytecode)
     719ALWAYS_INLINE BinaryArithProfile JIT::copiedArithProfile(BinaryOp bytecode)
    720720{
    721721    uint64_t key = (static_cast<uint64_t>(BinaryOp::opcodeID) + 1) << 32 | static_cast<uint64_t>(bytecode.m_metadataID);
     
    723723    if (iterator != m_copiedArithProfiles.end())
    724724        return iterator->value;
    725     ArithProfile arithProfile = bytecode.metadata(m_codeBlock).m_arithProfile;
     725    BinaryArithProfile arithProfile = bytecode.metadata(m_codeBlock).m_arithProfile;
    726726    m_copiedArithProfiles.add(key, arithProfile);
    727727    return arithProfile;
  • trunk/Source/JavaScriptCore/jit/JITMathIC.h

    r252273 r252422  
    5353#define ENABLE_MATH_IC_STATS 0
    5454
    55 template <typename GeneratorType, bool(*isProfileEmpty)(ArithProfile&)>
     55template <typename GeneratorType, typename ArithProfileType>
    5656class JITMathIC {
    5757    WTF_MAKE_FAST_ALLOCATED;
    5858public:
    59     JITMathIC(ArithProfile* arithProfile)
     59    JITMathIC(ArithProfileType* arithProfile)
    6060        : m_arithProfile(arithProfile)
    6161    {
     
    7272
    7373        if (m_arithProfile) {
    74             if (isProfileEmpty(*m_arithProfile)) {
     74            if (m_arithProfile->isObservedTypeEmpty()) {
    7575                // It looks like the MathIC has yet to execute. We don't want to emit code in this
    7676                // case for a couple reasons. First, the operation may never execute, so if we don't emit
     
    224224    }
    225225
    226     ArithProfile* arithProfile() const { return m_arithProfile; }
     226    ArithProfileType* arithProfile() const { return m_arithProfile; }
    227227
    228228#if ENABLE(MATH_IC_STATS)
     
    237237#endif
    238238
    239     ArithProfile* m_arithProfile;
     239    ArithProfileType* m_arithProfile;
    240240    MacroAssemblerCodeRef<JITStubRoutinePtrTag> m_code;
    241241    CodeLocationLabel<JSInternalPtrTag> m_inlineStart;
     
    247247};
    248248
    249 inline bool isBinaryProfileEmpty(ArithProfile& arithProfile)
    250 {
    251     return arithProfile.lhsObservedType().isEmpty() || arithProfile.rhsObservedType().isEmpty();
    252 }
    253249template <typename GeneratorType>
    254 class JITBinaryMathIC : public JITMathIC<GeneratorType, isBinaryProfileEmpty> {
     250class JITBinaryMathIC : public JITMathIC<GeneratorType, BinaryArithProfile> {
    255251public:
    256     JITBinaryMathIC(ArithProfile* arithProfile)
    257         : JITMathIC<GeneratorType, isBinaryProfileEmpty>(arithProfile)
     252    JITBinaryMathIC(BinaryArithProfile* arithProfile)
     253        : JITMathIC<GeneratorType, BinaryArithProfile>(arithProfile)
    258254    {
    259255    }
     
    264260typedef JITBinaryMathIC<JITSubGenerator> JITSubIC;
    265261
    266 
    267 inline bool isUnaryProfileEmpty(ArithProfile& arithProfile)
    268 {
    269     return arithProfile.lhsObservedType().isEmpty();
    270 }
    271262template <typename GeneratorType>
    272 class JITUnaryMathIC : public JITMathIC<GeneratorType, isUnaryProfileEmpty> {
     263class JITUnaryMathIC : public JITMathIC<GeneratorType, UnaryArithProfile> {
    273264public:
    274     JITUnaryMathIC(ArithProfile* arithProfile)
    275         : JITMathIC<GeneratorType, isUnaryProfileEmpty>(arithProfile)
     265    JITUnaryMathIC(UnaryArithProfile* arithProfile)
     266        : JITMathIC<GeneratorType, UnaryArithProfile>(arithProfile)
    276267    {
    277268    }
  • trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp

    r252273 r252422  
    3434namespace JSC {
    3535
    36 JITMathICInlineResult JITMulGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const ArithProfile* arithProfile)
     36JITMathICInlineResult JITMulGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const BinaryArithProfile* arithProfile)
    3737{
    3838    // We default to speculating int32.
     
    9090}
    9191
    92 bool JITMulGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling)
     92bool JITMulGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const BinaryArithProfile* arithProfile, bool shouldEmitProfiling)
    9393{
    9494    ASSERT(m_scratchGPR != InvalidGPRReg);
     
    206206        CCallHelpers::Jump notNegativeZero = jit.branch64(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm64(negativeZeroBits));
    207207
    208         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     208        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::NegZeroDouble);
    209209        CCallHelpers::Jump done = jit.jump();
    210210
    211211        notNegativeZero.link(&jit);
    212         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     212        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::NonNegZeroDouble);
    213213
    214214        jit.move(m_result.payloadGPR(), m_scratchGPR);
     
    217217        CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
    218218
    219         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     219        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::Int52Overflow);
    220220        noInt52Overflow.link(&jit);
    221221
     
    228228        notNegativeZero.append(jit.branch32(CCallHelpers::NotEqual, m_result.tagGPR(), CCallHelpers::TrustedImm32(negativeZeroBits >> 32)));
    229229
    230         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     230        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::NegZeroDouble);
    231231        CCallHelpers::Jump done = jit.jump();
    232232
    233233        notNegativeZero.link(&jit);
    234         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     234        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::NonNegZeroDouble);
    235235
    236236        jit.move(m_result.tagGPR(), m_scratchGPR);
     
    238238        jit.and32(CCallHelpers::Imm32(0x7ff), m_scratchGPR);
    239239        CCallHelpers::Jump noInt52Overflow = jit.branch32(CCallHelpers::LessThanOrEqual, m_scratchGPR, CCallHelpers::TrustedImm32(0x431));
    240        
    241         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(arithProfile->addressOfBits()));
     240
     241        arithProfile->emitUnconditionalSet(jit, BinaryArithProfile::Int52Overflow);
    242242
    243243        endJumpList.append(noInt52Overflow);
  • trunk/Source/JavaScriptCore/jit/JITMulGenerator.h

    r252273 r252422  
    5757    }
    5858
    59     JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const ArithProfile*);
    60     bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowJumpList, const ArithProfile*, bool shouldEmitProfiling);
     59    JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const BinaryArithProfile*);
     60    bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowJumpList, const BinaryArithProfile*, bool shouldEmitProfiling);
    6161
    6262    static bool isLeftOperandValidConstant(SnippetOperand leftOperand) { return leftOperand.isPositiveConstInt32(); }
  • trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp

    r252273 r252422  
    3333namespace JSC {
    3434
    35 JITMathICInlineResult JITNegGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const ArithProfile* arithProfile)
     35JITMathICInlineResult JITNegGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const UnaryArithProfile* arithProfile)
    3636{
    3737    ASSERT(m_scratchGPR != InvalidGPRReg);
     
    4646    ObservedType observedTypes = ObservedType().withInt32();
    4747    if (arithProfile)
    48         observedTypes = arithProfile->lhsObservedType();
     48        observedTypes = arithProfile->argObservedType();
    4949    ASSERT_WITH_MESSAGE(!observedTypes.isEmpty(), "We should not attempt to generate anything if we do not have a profile.");
    5050
     
    8383}
    8484
    85 bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling)
     85bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const UnaryArithProfile* arithProfile, bool shouldEmitProfiling)
    8686{
    8787    ASSERT(m_scratchGPR != m_src.payloadGPR());
     
    118118    // The flags of ArithNegate are basic in DFG.
    119119    // We only need to know if we ever produced a number.
    120     if (shouldEmitProfiling && arithProfile && !arithProfile->lhsObservedType().sawNumber() && !arithProfile->didObserveDouble())
     120    if (shouldEmitProfiling && arithProfile && !arithProfile->argObservedType().sawNumber() && !arithProfile->didObserveDouble())
    121121        arithProfile->emitSetDouble(jit);
    122122    return true;
  • trunk/Source/JavaScriptCore/jit/JITNegGenerator.h

    r252273 r252422  
    4444    { }
    4545
    46     JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const ArithProfile*);
    47     bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile*, bool shouldEmitProfiling);
     46    JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const UnaryArithProfile*);
     47    bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const UnaryArithProfile*, bool shouldEmitProfiling);
    4848
    4949private:
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r252273 r252422  
    26462646}
    26472647
    2648 ALWAYS_INLINE static JSValue profiledAdd(JSGlobalObject* globalObject, JSValue op1, JSValue op2, ArithProfile& arithProfile)
     2648ALWAYS_INLINE static JSValue profiledAdd(JSGlobalObject* globalObject, JSValue op1, JSValue op2, BinaryArithProfile& arithProfile)
    26492649{
    26502650    arithProfile.observeLHSAndRHS(op1, op2);
     
    26622662}
    26632663
    2664 EncodedJSValue JIT_OPERATION operationValueAddProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
     2664EncodedJSValue JIT_OPERATION operationValueAddProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile)
    26652665{
    26662666    ASSERT(arithProfile);
     
    26802680    JSValue op2 = JSValue::decode(encodedOp2);
    26812681
    2682     ArithProfile* arithProfile = addIC->arithProfile();
     2682    BinaryArithProfile* arithProfile = addIC->arithProfile();
    26832683    ASSERT(arithProfile);
    26842684    arithProfile->observeLHSAndRHS(op1, op2);
     
    27022702    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    27032703
    2704     ArithProfile* arithProfile = addIC->arithProfile();
     2704    BinaryArithProfile* arithProfile = addIC->arithProfile();
    27052705    ASSERT(arithProfile);
    27062706    return JSValue::encode(profiledAdd(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2), *arithProfile));
     
    27172717
    27182718    auto nonOptimizeVariant = operationValueAddNoOptimize;
    2719     if (ArithProfile* arithProfile = addIC->arithProfile())
     2719    if (BinaryArithProfile* arithProfile = addIC->arithProfile())
    27202720        arithProfile->observeLHSAndRHS(op1, op2);
    27212721    addIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
     
    27502750}
    27512751
    2752 ALWAYS_INLINE static EncodedJSValue profiledMul(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
     2752ALWAYS_INLINE static EncodedJSValue profiledMul(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
    27532753{
    27542754    VM& vm = globalObject->vm();
     
    27912791
    27922792    auto nonOptimizeVariant = operationValueMulNoOptimize;
    2793     if (ArithProfile* arithProfile = mulIC->arithProfile())
     2793    if (BinaryArithProfile* arithProfile = mulIC->arithProfile())
    27942794        arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
    27952795    mulIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
     
    28022802}
    28032803
    2804 EncodedJSValue JIT_OPERATION operationValueMulProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
     2804EncodedJSValue JIT_OPERATION operationValueMulProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile)
    28052805{
    28062806    VM& vm = globalObject->vm();
     
    28182818    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    28192819
    2820     ArithProfile* arithProfile = mulIC->arithProfile();
     2820    BinaryArithProfile* arithProfile = mulIC->arithProfile();
    28212821    ASSERT(arithProfile);
    28222822    arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
     
    28372837    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    28382838
    2839     ArithProfile* arithProfile = mulIC->arithProfile();
     2839    BinaryArithProfile* arithProfile = mulIC->arithProfile();
    28402840    ASSERT(arithProfile);
    28412841    return profiledMul(globalObject, encodedOp1, encodedOp2, *arithProfile);
     
    28632863}
    28642864
    2865 EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOperand, ArithProfile* arithProfile)
     2865EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOperand, UnaryArithProfile* arithProfile)
    28662866{
    28672867    ASSERT(arithProfile);
     
    28722872
    28732873    JSValue operand = JSValue::decode(encodedOperand);
    2874     arithProfile->observeLHS(operand);
     2874    arithProfile->observeArg(operand);
    28752875
    28762876    JSValue primValue = operand.toPrimitive(globalObject);
     
    29002900    JSValue operand = JSValue::decode(encodedOperand);
    29012901
    2902     ArithProfile* arithProfile = negIC->arithProfile();
     2902    UnaryArithProfile* arithProfile = negIC->arithProfile();
    29032903    ASSERT(arithProfile);
    2904     arithProfile->observeLHS(operand);
     2904    arithProfile->observeArg(operand);
    29052905    negIC->generateOutOfLine(callFrame->codeBlock(), operationArithNegateProfiled);
    29062906
     
    29342934    JSValue operand = JSValue::decode(encodedOperand);
    29352935
    2936     if (ArithProfile* arithProfile = negIC->arithProfile())
    2937         arithProfile->observeLHS(operand);
     2936    if (UnaryArithProfile* arithProfile = negIC->arithProfile())
     2937        arithProfile->observeArg(operand);
    29382938    negIC->generateOutOfLine(callFrame->codeBlock(), operationArithNegate);
    29392939
     
    29612961}
    29622962
    2963 ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
     2963ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
    29642964{
    29652965    auto scope = DECLARE_THROW_SCOPE(vm);
     
    29852985}
    29862986
    2987 EncodedJSValue JIT_OPERATION operationValueSubProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
     2987EncodedJSValue JIT_OPERATION operationValueSubProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile)
    29882988{
    29892989    ASSERT(arithProfile);
     
    30033003
    30043004    auto nonOptimizeVariant = operationValueSubNoOptimize;
    3005     if (ArithProfile* arithProfile = subIC->arithProfile())
     3005    if (BinaryArithProfile* arithProfile = subIC->arithProfile())
    30063006        arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
    30073007    subIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
     
    30293029    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    30303030
    3031     ArithProfile* arithProfile = subIC->arithProfile();
     3031    BinaryArithProfile* arithProfile = subIC->arithProfile();
    30323032    ASSERT(arithProfile);
    30333033    arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
     
    30483048    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    30493049
    3050     ArithProfile* arithProfile = subIC->arithProfile();
     3050    BinaryArithProfile* arithProfile = subIC->arithProfile();
    30513051    ASSERT(arithProfile);
    30523052    return profiledSub(vm, globalObject, encodedOp1, encodedOp2, *arithProfile);
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r252273 r252422  
    3939class ArrayAllocationProfile;
    4040class ArrayProfile;
     41class UnaryArithProfile;
     42class BinaryArithProfile;
    4143class Butterfly;
    4244class CallFrame;
     
    6567struct InlineCallFrame;
    6668struct Instruction;
    67 struct ArithProfile;
    6869
    6970extern "C" {
     
    7879    Aap: ArrayAllocationProfile*
    7980    Ap: ArrayProfile*
    80     Arp: ArithProfile*
     81    Arp: BinaryArithProfile*
    8182    B: Butterfly*
    8283    By: ByValInfo*
     
    283284
    284285EncodedJSValue JIT_OPERATION operationValueAdd(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
    285 EncodedJSValue JIT_OPERATION operationValueAddProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
     286EncodedJSValue JIT_OPERATION operationValueAddProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile*) WTF_INTERNAL;
    286287EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
    287288EncodedJSValue JIT_OPERATION operationValueAddProfiledNoOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
     
    293294EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*) WTF_INTERNAL;
    294295EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*) WTF_INTERNAL;
    295 EncodedJSValue JIT_OPERATION operationValueMulProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
     296EncodedJSValue JIT_OPERATION operationValueMulProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile*) WTF_INTERNAL;
    296297EncodedJSValue JIT_OPERATION operationArithNegate(JSGlobalObject*, EncodedJSValue operand);
    297 EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject*, EncodedJSValue operand, ArithProfile*);
     298EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject*, EncodedJSValue operand, UnaryArithProfile*);
    298299EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(JSGlobalObject*, EncodedJSValue encodedOperand, JITNegIC*);
    299300EncodedJSValue JIT_OPERATION operationArithNegateOptimize(JSGlobalObject*, EncodedJSValue encodedOperand, JITNegIC*);
    300301EncodedJSValue JIT_OPERATION operationValueSub(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
    301 EncodedJSValue JIT_OPERATION operationValueSubProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
     302EncodedJSValue JIT_OPERATION operationValueSubProfiled(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile*) WTF_INTERNAL;
    302303EncodedJSValue JIT_OPERATION operationValueSubOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*) WTF_INTERNAL;
    303304EncodedJSValue JIT_OPERATION operationValueSubNoOptimize(JSGlobalObject*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/JITSubGenerator.cpp

    r252273 r252422  
    3434namespace JSC {
    3535
    36 JITMathICInlineResult JITSubGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const ArithProfile* arithProfile)
     36JITMathICInlineResult JITSubGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state, const BinaryArithProfile* arithProfile)
    3737{
    3838    // We default to speculating int32.
     
    7979}
    8080
    81 bool JITSubGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling)
     81bool JITSubGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const BinaryArithProfile* arithProfile, bool shouldEmitProfiling)
    8282{
    8383    ASSERT(m_scratchGPR != InvalidGPRReg);
  • trunk/Source/JavaScriptCore/jit/JITSubGenerator.h

    r252273 r252422  
    5454    { }
    5555
    56     JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const ArithProfile*);
    57     bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile*, bool shouldEmitProfiling);
     56    JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&, const BinaryArithProfile*);
     57    bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const BinaryArithProfile*, bool shouldEmitProfiling);
    5858
    5959    static bool isLeftOperandValidConstant(SnippetOperand) { return false; }
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r252273 r252422  
    148148
    149149    {
    150         ArithProfile arithProfile;
     150        UnaryArithProfile arithProfile;
     151        arithProfile.argSawInt32();
     152        ASSERT(arithProfile.bits() == UnaryArithProfile::observedIntBits());
     153        ASSERT(arithProfile.argObservedType().isOnlyInt32());
     154    }
     155    {
     156        UnaryArithProfile arithProfile;
     157        arithProfile.argSawNumber();
     158        ASSERT(arithProfile.bits() == UnaryArithProfile::observedNumberBits());
     159        ASSERT(arithProfile.argObservedType().isOnlyNumber());
     160    }
     161
     162    {
     163        BinaryArithProfile arithProfile;
    151164        arithProfile.lhsSawInt32();
    152165        arithProfile.rhsSawInt32();
    153         ASSERT(arithProfile.bits() == ArithProfile::observedBinaryIntInt().bits());
    154         STATIC_ASSERT(ArithProfile::observedBinaryIntInt().lhsObservedType().isOnlyInt32());
    155         STATIC_ASSERT(ArithProfile::observedBinaryIntInt().rhsObservedType().isOnlyInt32());
     166        ASSERT(arithProfile.bits() == BinaryArithProfile::observedIntIntBits());
     167        ASSERT(arithProfile.lhsObservedType().isOnlyInt32());
     168        ASSERT(arithProfile.rhsObservedType().isOnlyInt32());
    156169    }
    157170    {
    158         ArithProfile arithProfile;
     171        BinaryArithProfile arithProfile;
    159172        arithProfile.lhsSawNumber();
    160173        arithProfile.rhsSawInt32();
    161         ASSERT(arithProfile.bits() == ArithProfile::observedBinaryNumberInt().bits());
    162         STATIC_ASSERT(ArithProfile::observedBinaryNumberInt().lhsObservedType().isOnlyNumber());
    163         STATIC_ASSERT(ArithProfile::observedBinaryNumberInt().rhsObservedType().isOnlyInt32());
     174        ASSERT(arithProfile.bits() == BinaryArithProfile::observedNumberIntBits());
     175        ASSERT(arithProfile.lhsObservedType().isOnlyNumber());
     176        ASSERT(arithProfile.rhsObservedType().isOnlyInt32());
    164177    }
    165178    {
    166         ArithProfile arithProfile;
     179        BinaryArithProfile arithProfile;
    167180        arithProfile.lhsSawNumber();
    168181        arithProfile.rhsSawNumber();
    169         ASSERT(arithProfile.bits() == ArithProfile::observedBinaryNumberNumber().bits());
    170         STATIC_ASSERT(ArithProfile::observedBinaryNumberNumber().lhsObservedType().isOnlyNumber());
    171         STATIC_ASSERT(ArithProfile::observedBinaryNumberNumber().rhsObservedType().isOnlyNumber());
     182        ASSERT(arithProfile.bits() == BinaryArithProfile::observedNumberNumberBits());
     183        ASSERT(arithProfile.lhsObservedType().isOnlyNumber());
     184        ASSERT(arithProfile.rhsObservedType().isOnlyNumber());
    172185    }
    173186    {
    174         ArithProfile arithProfile;
     187        BinaryArithProfile arithProfile;
    175188        arithProfile.lhsSawInt32();
    176189        arithProfile.rhsSawNumber();
    177         ASSERT(arithProfile.bits() == ArithProfile::observedBinaryIntNumber().bits());
    178         STATIC_ASSERT(ArithProfile::observedBinaryIntNumber().lhsObservedType().isOnlyInt32());
    179         STATIC_ASSERT(ArithProfile::observedBinaryIntNumber().rhsObservedType().isOnlyNumber());
     190        ASSERT(arithProfile.bits() == BinaryArithProfile::observedIntNumberBits());
     191        ASSERT(arithProfile.lhsObservedType().isOnlyInt32());
     192        ASSERT(arithProfile.rhsObservedType().isOnlyNumber());
    180193    }
    181194}
  • trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp

    r252273 r252422  
    9292const int64_t* LLIntOffsetsExtractor::dummy()
    9393{
    94 // This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code
     94// This is a file generated by offlineasm/generate_offset_extractor.rb, and contains code
    9595// to create a table of offsets, sizes, and a header identifying what combination of
    9696// Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r252302 r252422  
    242242const ShadowChickenTailMarker = constexpr ShadowChicken::Packet::tailMarkerValue
    243243
    244 # ArithProfile data
    245 const ArithProfileInt = constexpr (ArithProfile::observedUnaryInt().bits())
    246 const ArithProfileNumber = constexpr (ArithProfile::observedUnaryNumber().bits())
    247 const ArithProfileIntInt = constexpr (ArithProfile::observedBinaryIntInt().bits())
    248 const ArithProfileNumberInt = constexpr (ArithProfile::observedBinaryNumberInt().bits())
    249 const ArithProfileIntNumber = constexpr (ArithProfile::observedBinaryIntNumber().bits())
    250 const ArithProfileNumberNumber = constexpr (ArithProfile::observedBinaryNumberNumber().bits())
     244# UnaryArithProfile data
     245const ArithProfileInt = constexpr (UnaryArithProfile::observedIntBits())
     246const ArithProfileNumber = constexpr (UnaryArithProfile::observedNumberBits())
     247
     248# BinaryArithProfile data
     249const ArithProfileIntInt = constexpr (BinaryArithProfile::observedIntIntBits())
     250const ArithProfileNumberInt = constexpr (BinaryArithProfile::observedNumberIntBits())
     251const ArithProfileIntNumber = constexpr (BinaryArithProfile::observedIntNumberBits())
     252const ArithProfileNumberNumber = constexpr (BinaryArithProfile::observedNumberNumberBits())
    251253
    252254# Pointer Tags
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r252273 r252422  
    10011001llintOpWithMetadata(op_negate, OpNegate, macro (size, get, dispatch, metadata, return)
    10021002
    1003     macro arithProfile(type)
    1004         ori type, OpNegate::Metadata::m_arithProfile + ArithProfile::m_bits[t5]
     1003    macro updateArithProfile(type)
     1004        orh type, OpNegate::Metadata::m_arithProfile + UnaryArithProfile::m_bits[t5]
    10051005    end
    10061006
     
    10111011    btiz t2, 0x7fffffff, .opNegateSlow
    10121012    negi t2
    1013     arithProfile(ArithProfileInt)
     1013    updateArithProfile(ArithProfileInt)
    10141014    return (Int32Tag, t2)
    10151015.opNegateSrcNotInt:
    10161016    bia t1, LowestTag, .opNegateSlow
    10171017    xori 0x80000000, t1
    1018     arithProfile(ArithProfileNumber)
     1018    updateArithProfile(ArithProfileNumber)
    10191019    return(t1, t2)
    10201020
     
    10281028    llintOpWithMetadata(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, metadata, return)
    10291029        macro arithProfile(type)
    1030             ori type, %opcodeStruct%::Metadata::m_arithProfile + ArithProfile::m_bits[t5]
     1030            orh type, %opcodeStruct%::Metadata::m_arithProfile + BinaryArithProfile::m_bits[t5]
    10311031        end
    10321032
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r252273 r252422  
    982982
    983983llintOpWithMetadata(op_negate, OpNegate, macro (size, get, dispatch, metadata, return)
     984
     985    macro updateArithProfile(type)
     986        orh type, OpNegate::Metadata::m_arithProfile + UnaryArithProfile::m_bits[t1]
     987    end
     988
    984989    get(m_operand, t0)
    985990    loadConstantOrVariable(size, t0, t3)
    986991    metadata(t1, t2)
    987     loadi OpNegate::Metadata::m_arithProfile + ArithProfile::m_bits[t1], t2
    988992    bqb t3, numberTag, .opNegateNotInt
    989993    btiz t3, 0x7fffffff, .opNegateSlow
    990994    negi t3
    991995    orq numberTag, t3
    992     ori ArithProfileInt, t2
    993     storei t2, OpNegate::Metadata::m_arithProfile + ArithProfile::m_bits[t1]
     996    updateArithProfile(ArithProfileInt)
    994997    return(t3)
    995998.opNegateNotInt:
    996999    btqz t3, numberTag, .opNegateSlow
    9971000    xorq 0x8000000000000000, t3
    998     ori ArithProfileNumber, t2
    999     storei t2, OpNegate::Metadata::m_arithProfile + ArithProfile::m_bits[t1]
     1001    updateArithProfile(ArithProfileNumber)
    10001002    return(t3)
    10011003
     
    10111013
    10121014        macro profile(type)
    1013             ori type, %opcodeStruct%::Metadata::m_arithProfile + ArithProfile::m_bits[t5]
     1015            orh type, %opcodeStruct%::Metadata::m_arithProfile + UnaryArithProfile::m_bits[t5]
    10141016        end
    10151017
  • trunk/Source/JavaScriptCore/offlineasm/arm.rb

    r252273 r252422  
    300300        }
    301301        result = riscLowerMalformedAddressesDouble(result)
    302         result = riscLowerMisplacedImmediates(result, ["storeb", "storei", "storep", "storeq"])
     302        result = riscLowerMisplacedImmediates(result, ["storeb", "storeh", "storei", "storep", "storeq"])
    303303        result = riscLowerMalformedImmediates(result, 0..0xff, 0..0x0ff)
    304304        result = riscLowerMisplacedAddresses(result)
     
    419419        when "andi", "andp"
    420420            emitArmCompact("ands", "and", operands)
    421         when "ori", "orp"
     421        when "ori", "orp", "orh"
    422422            emitArmCompact("orrs", "orr", operands)
    423423        when "oris"
  • trunk/Source/JavaScriptCore/offlineasm/arm64.rb

    r252273 r252422  
    394394            when "loadb", "loadbsi", "loadbsq", "storeb", /^bb/, /^btb/, /^cb/, /^tb/
    395395                size = 1
    396             when "loadh", "loadhsi", "loadhsq", "storeh"
     396            when "loadh", "loadhsi", "loadhsq", "orh", "storeh"
    397397                size = 2
    398398            when "loadi", "loadis", "storei", "addi", "andi", "lshifti", "muli", "negi",
     
    419419        }
    420420
    421         result = riscLowerMisplacedImmediates(result, ["storeb", "storei", "storep", "storeq"])
     421        result = riscLowerMisplacedImmediates(result, ["storeb", "storeh", "storei", "storep", "storeq"])
    422422
    423423        # The rules for which immediates are valid for and/or/xor instructions are fairly involved, see https://dinfuehr.github.io/blog/encoding-of-immediate-values-on-aarch64/
     
    712712        when "orq"
    713713            emitARM64TAC("orr", operands, :quad)
     714        when "orh"
     715            emitARM64TAC("orr", operands, :word) # not :half because 16-bit registers don't exist on ARM.
    714716        when "xori"
    715717            emitARM64TAC("eor", operands, :word)
  • trunk/Source/JavaScriptCore/offlineasm/cloop.rb

    r252273 r252422  
    161161        case type
    162162        when :int8;    "int8_t(#{valueStr})"
     163        when :int16;   "int16_t(#{valueStr})"
    163164        when :int32;   "int32_t(#{valueStr})"
    164165        when :int64;   "int64_t(#{valueStr})"
     
    184185        case type
    185186        when :int8;         int8MemRef
     187        when :int16;        int16MemRef
    186188        when :int32;        int32MemRef
    187189        when :int64;        int64MemRef
     
    387389def cloopEmitOperation(operands, type, operator)
    388390    raise unless type == :intptr || type == :uintptr || type == :int32 || type == :uint32 || \
    389         type == :int64 || type == :uint64 || type == :double
     391        type == :int64 || type == :uint64 || type == :double || type == :int16
    390392    if operands.size == 3
    391393        op1 = operands[0]
     
    401403    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
    402404        truncationHeader = "(uint32_t)("
     405        truncationFooter = ")"
     406    elsif dst.is_a? RegisterID and (type == :int16)
     407        truncationHeader = "(uint16_t)("
    403408        truncationFooter = ")"
    404409    else
     
    586591        when "orp"
    587592            cloopEmitOperation(operands, :intptr, "|")
     593        when "orh"
     594            cloopEmitOperation(operands, :int16, "|")
    588595
    589596        when "xori"
  • trunk/Source/JavaScriptCore/offlineasm/instructions.rb

    r252273 r252422  
    4747     "orf",
    4848     "ord",
     49     "orh",
    4950     "rshifti",
    5051     "urshifti",
  • trunk/Source/JavaScriptCore/offlineasm/mips.rb

    r252273 r252422  
    528528            when /^(addi|subi)/
    529529                newList << node.riscLowerMalformedImmediatesRecurse(newList, -0x7fff..0x7fff)
    530             when "andi", "andp", "ori", "orp", "xori", "xorp"
     530            when "andi", "andp", "ori", "orp", "orh", "xori", "xorp"
    531531                newList << node.riscLowerMalformedImmediatesRecurse(newList, 0..0xffff)
    532532            else
     
    861861        when "andi", "andp"
    862862            emitMIPSCompact("and", "and", operands)
    863         when "ori", "orp"
     863        when "ori", "orp", "orh"
    864864            emitMIPSCompact("or", "orr", operands)
    865865        when "oris"
  • trunk/Source/JavaScriptCore/offlineasm/risc.rb

    r252273 r252422  
    463463            annotation = node.annotation
    464464            case node.opcode
    465             when "addi", "addis", "andi", "lshifti", "muli", "negi", "noti", "ori", "oris",
     465            when "addi", "addis", "andi", "lshifti", "muli", "negi", "noti", "ori", "orh", "oris",
    466466                "rshifti", "urshifti", "subi", "subis", "xori", /^bi/, /^bti/, /^ci/, /^ti/
    467467                newList << Instruction.new(node.codeOrigin,
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r252273 r252422  
    11241124        when "ord"
    11251125            handleX86Op("orpd", :double)
     1126        when "orh"
     1127            handleX86Op("or#{x86Suffix(:half)}", :half)
    11261128        when "rshifti"
    11271129            handleX86Shift("sar#{x86Suffix(:int)}", :int)
  • trunk/Source/JavaScriptCore/parser/ResultType.h

    r252273 r252422  
    4949        static_assert((TypeBits & ((1 << numBitsNeeded) - 1)) == TypeBits, "This is necessary for correctness.");
    5050
     51        constexpr explicit ResultType()
     52            : ResultType(unknownType())
     53        {
     54        }
    5155        constexpr explicit ResultType(Type type)
    5256            : m_bits(type)
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r252273 r252422  
    478478static void updateArithProfileForUnaryArithOp(OpNegate::Metadata& metadata, JSValue result, JSValue operand)
    479479{
    480     ArithProfile& profile = metadata.m_arithProfile;
    481     profile.observeLHS(operand);
     480    UnaryArithProfile& profile = metadata.m_arithProfile;
     481    profile.observeArg(operand);
    482482    ASSERT(result.isNumber() || result.isBigInt());
    483483    if (result.isNumber()) {
     
    536536static void updateArithProfileForBinaryArithOp(JSGlobalObject*, CodeBlock* codeBlock, const Instruction* pc, JSValue result, JSValue left, JSValue right)
    537537{
    538     ArithProfile& profile = *codeBlock->arithProfileForPC(pc);
     538    BinaryArithProfile& profile = *codeBlock->binaryArithProfileForPC(pc);
    539539
    540540    if (result.isNumber()) {
     
    597597    JSValue v2 = GET_C(bytecode.m_rhs).jsValue();
    598598
    599     ArithProfile& arithProfile = *codeBlock->arithProfileForPC(pc);
     599    BinaryArithProfile& arithProfile = *codeBlock->binaryArithProfileForPC(pc);
    600600    arithProfile.observeLHSAndRHS(v1, v2);
    601601
Note: See TracChangeset for help on using the changeset viewer.