Ignore:
Timestamp:
Nov 13, 2019, 12:07:29 PM (6 years ago)
Author:
[email protected]
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):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.