Ignore:
Timestamp:
Sep 17, 2013, 6:31:04 PM (12 years ago)
Author:
[email protected]
Message:

DFG should support Int52 for local variables
https://bugs.webkit.org/show_bug.cgi?id=121064

Source/JavaScriptCore:

Reviewed by Oliver Hunt.

This adds Int52 support for local variables to the DFG and FTL. It's a speed-up on
programs that have local int32 overflows but where a larger int representation can
prevent us from having to convert all the way up to double.

It's a small speed-up for now. But we're just supporting Int52 for a handful of
operations (add, sub, mul, neg, compare, bitops, typed array access) and this lays
the groundwork for adding Int52 to JSValue, which will probably be a bigger
speed-up.

The basic approach is:

  • We have a notion of Int52 in our typesystem. Int52 doesn't belong to BytecodeTop or HeapTop - i.e. it doesn't arise from JSValues.


  • DFG treats Int52 as being part of its FullTop and will treat it as being a subtype of double unless instructed otherwise.


  • Prediction propagator creates Int52s whenever we have a node going doubly but due to large values rather than fractional values, and that node is known to be able to produce Int52 natively in the DFG backend.


  • Fixup phase converts edges to MachineIntUses in nodes that are known to be able to deal with Int52, and where we have a subtype of Int32|Int52 as the predicted input.


  • The DFG backend and FTL LLVM IR lowering have two notions of Int52s - ones that are left-shifted by 16 (great for overflow checks) and ones that are sign-extended. Both backends know how to convert between Int52s and the other representations.
  • assembler/MacroAssemblerX86_64.h:

(JSC::MacroAssemblerX86_64::rshift64):
(JSC::MacroAssemblerX86_64::mul64):
(JSC::MacroAssemblerX86_64::branchMul64):
(JSC::MacroAssemblerX86_64::branchNeg64):
(JSC::MacroAssemblerX86_64::convertInt64ToDouble):

  • assembler/X86Assembler.h:

(JSC::X86Assembler::imulq_rr):
(JSC::X86Assembler::cvtsi2sdq_rr):

  • bytecode/DataFormat.h:

(JSC::dataFormatToString):

  • bytecode/OperandsInlines.h:

(JSC::::dumpInContext):

  • bytecode/SpeculatedType.cpp:

(JSC::dumpSpeculation):
(JSC::speculationToAbbreviatedString):
(JSC::speculationFromValue):

  • bytecode/SpeculatedType.h:

(JSC::isInt32SpeculationForArithmetic):
(JSC::isMachineIntSpeculationForArithmetic):
(JSC::isBytecodeRealNumberSpeculation):
(JSC::isFullRealNumberSpeculation):
(JSC::isBytecodeNumberSpeculation):
(JSC::isFullNumberSpeculation):
(JSC::isBytecodeNumberSpeculationExpectingDefined):
(JSC::isFullNumberSpeculationExpectingDefined):

  • bytecode/ValueRecovery.h:

(JSC::ValueRecovery::alreadyInJSStackAsUnboxedInt52):
(JSC::ValueRecovery::inGPR):
(JSC::ValueRecovery::displacedInJSStack):
(JSC::ValueRecovery::isAlreadyInJSStack):
(JSC::ValueRecovery::gpr):
(JSC::ValueRecovery::virtualRegister):
(JSC::ValueRecovery::dumpInContext):

  • dfg/DFGAbstractInterpreter.h:

(JSC::DFG::AbstractInterpreter::needsTypeCheck):
(JSC::DFG::AbstractInterpreter::filterByType):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::::executeEffects):

  • dfg/DFGAbstractValue.cpp:

(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::checkConsistency):

  • dfg/DFGAbstractValue.h:

(JSC::DFG::AbstractValue::couldBeType):
(JSC::DFG::AbstractValue::isType):
(JSC::DFG::AbstractValue::checkConsistency):
(JSC::DFG::AbstractValue::validateType):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::refine):

  • dfg/DFGAssemblyHelpers.h:

(JSC::DFG::AssemblyHelpers::boxInt52):

  • dfg/DFGCSEPhase.cpp:

(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGCommon.h:

(JSC::DFG::enableInt52):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::run):
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupSetLocalsInBlock):
(JSC::DFG::FixupPhase::fixupUntypedSetLocalsInBlock):
(JSC::DFG::FixupPhase::observeUseKindOnNode):
(JSC::DFG::FixupPhase::fixEdge):
(JSC::DFG::FixupPhase::injectInt32ToDoubleNode):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):

  • dfg/DFGFlushFormat.cpp:

(WTF::printInternal):

  • dfg/DFGFlushFormat.h:

(JSC::DFG::resultFor):
(JSC::DFG::useKindFor):

  • dfg/DFGGenerationInfo.h:

(JSC::DFG::GenerationInfo::initInt52):
(JSC::DFG::GenerationInfo::initStrictInt52):
(JSC::DFG::GenerationInfo::isFormat):
(JSC::DFG::GenerationInfo::isInt52):
(JSC::DFG::GenerationInfo::isStrictInt52):
(JSC::DFG::GenerationInfo::fillInt52):
(JSC::DFG::GenerationInfo::fillStrictInt52):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::addShouldSpeculateMachineInt):
(JSC::DFG::Graph::mulShouldSpeculateMachineInt):
(JSC::DFG::Graph::negateShouldSpeculateMachineInt):

  • dfg/DFGInPlaceAbstractState.cpp:

(JSC::DFG::InPlaceAbstractState::mergeStateAtTail):

  • dfg/DFGJITCode.cpp:

(JSC::DFG::JITCode::reconstruct):

  • dfg/DFGMinifiedNode.h:

(JSC::DFG::belongsInMinifiedGraph):
(JSC::DFG::MinifiedNode::hasChild):

  • dfg/DFGNode.h:

(JSC::DFG::Node::shouldSpeculateNumber):
(JSC::DFG::Node::shouldSpeculateNumberExpectingDefined):

  • dfg/DFGNodeFlags.h:
  • dfg/DFGNodeType.h:

(JSC::DFG::forwardRewiringSelectionScore):

  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompiler64.cpp:

(JSC::DFG::OSRExitCompiler::compileExit):

  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::speculatedDoubleTypeForPrediction):
(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::doDoubleVoting):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):

  • dfg/DFGSilentRegisterSavePlan.h:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
(JSC::DFG::SpeculativeJIT::silentFill):
(JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
(JSC::DFG::SpeculativeJIT::compileInlineStart):
(JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
(JSC::DFG::SpeculativeJIT::compileValueToInt32):
(JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileAdd):
(JSC::DFG::SpeculativeJIT::compileArithSub):
(JSC::DFG::SpeculativeJIT::compileArithNegate):
(JSC::DFG::SpeculativeJIT::compileArithMul):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::speculateMachineInt):
(JSC::DFG::SpeculativeJIT::speculateNumber):
(JSC::DFG::SpeculativeJIT::speculateRealNumber):
(JSC::DFG::SpeculativeJIT::speculate):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::canReuse):
(JSC::DFG::SpeculativeJIT::isFilled):
(JSC::DFG::SpeculativeJIT::isFilledDouble):
(JSC::DFG::SpeculativeJIT::use):
(JSC::DFG::SpeculativeJIT::isKnownInteger):
(JSC::DFG::SpeculativeJIT::isKnownCell):
(JSC::DFG::SpeculativeJIT::isKnownNotNumber):
(JSC::DFG::SpeculativeJIT::int52Result):
(JSC::DFG::SpeculativeJIT::strictInt52Result):
(JSC::DFG::SpeculativeJIT::initConstantInfo):
(JSC::DFG::SpeculativeJIT::isInteger):
(JSC::DFG::SpeculativeJIT::betterUseStrictInt52):
(JSC::DFG::SpeculativeJIT::generationInfo):
(JSC::DFG::SpeculateInt52Operand::SpeculateInt52Operand):
(JSC::DFG::SpeculateInt52Operand::~SpeculateInt52Operand):
(JSC::DFG::SpeculateInt52Operand::edge):
(JSC::DFG::SpeculateInt52Operand::node):
(JSC::DFG::SpeculateInt52Operand::gpr):
(JSC::DFG::SpeculateInt52Operand::use):
(JSC::DFG::SpeculateStrictInt52Operand::SpeculateStrictInt52Operand):
(JSC::DFG::SpeculateStrictInt52Operand::~SpeculateStrictInt52Operand):
(JSC::DFG::SpeculateStrictInt52Operand::edge):
(JSC::DFG::SpeculateStrictInt52Operand::node):
(JSC::DFG::SpeculateStrictInt52Operand::gpr):
(JSC::DFG::SpeculateStrictInt52Operand::use):
(JSC::DFG::SpeculateWhicheverInt52Operand::SpeculateWhicheverInt52Operand):
(JSC::DFG::SpeculateWhicheverInt52Operand::~SpeculateWhicheverInt52Operand):
(JSC::DFG::SpeculateWhicheverInt52Operand::edge):
(JSC::DFG::SpeculateWhicheverInt52Operand::node):
(JSC::DFG::SpeculateWhicheverInt52Operand::gpr):
(JSC::DFG::SpeculateWhicheverInt52Operand::use):
(JSC::DFG::SpeculateWhicheverInt52Operand::format):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::boxInt52):
(JSC::DFG::SpeculativeJIT::fillJSValue):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileInt52Compare):
(JSC::DFG::SpeculativeJIT::compilePeepHoleInt52Branch):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::isNumerical):

  • dfg/DFGValueSource.cpp:

(JSC::DFG::ValueSource::dump):

  • dfg/DFGValueSource.h:

(JSC::DFG::dataFormatToValueSourceKind):
(JSC::DFG::valueSourceKindToDataFormat):
(JSC::DFG::ValueSource::forFlushFormat):
(JSC::DFG::ValueSource::valueRecovery):

  • dfg/DFGVariableAccessData.h:

(JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote):
(JSC::DFG::VariableAccessData::flushFormat):

  • ftl/FTLCArgumentGetter.cpp:

(JSC::FTL::CArgumentGetter::loadNextAndBox):

  • ftl/FTLCArgumentGetter.h:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLExitValue.cpp:

(JSC::FTL::ExitValue::dumpInContext):

  • ftl/FTLExitValue.h:

(JSC::FTL::ExitValue::inJSStackAsInt52):

  • ftl/FTLIntrinsicRepository.h:
  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::createPhiVariables):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileUpsilon):
(JSC::FTL::LowerDFGToLLVM::compilePhi):
(JSC::FTL::LowerDFGToLLVM::compileSetLocal):
(JSC::FTL::LowerDFGToLLVM::compileAdd):
(JSC::FTL::LowerDFGToLLVM::compileArithSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::compileCompareEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareLess):
(JSC::FTL::LowerDFGToLLVM::compileCompareLessEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareGreater):
(JSC::FTL::LowerDFGToLLVM::compileCompareGreaterEq):
(JSC::FTL::LowerDFGToLLVM::lowInt32):
(JSC::FTL::LowerDFGToLLVM::lowInt52):
(JSC::FTL::LowerDFGToLLVM::lowStrictInt52):
(JSC::FTL::LowerDFGToLLVM::betterUseStrictInt52):
(JSC::FTL::LowerDFGToLLVM::bestInt52Kind):
(JSC::FTL::LowerDFGToLLVM::opposite):
(JSC::FTL::LowerDFGToLLVM::Int52s::operator[]):
(JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52):
(JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52s):
(JSC::FTL::LowerDFGToLLVM::lowOpposingInt52s):
(JSC::FTL::LowerDFGToLLVM::lowCell):
(JSC::FTL::LowerDFGToLLVM::lowBoolean):
(JSC::FTL::LowerDFGToLLVM::lowDouble):
(JSC::FTL::LowerDFGToLLVM::lowJSValue):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToInt32):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToDouble):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToJSValue):
(JSC::FTL::LowerDFGToLLVM::setInt52WithStrictValue):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToInt52):
(JSC::FTL::LowerDFGToLLVM::int52ToStrictInt52):
(JSC::FTL::LowerDFGToLLVM::speculateRealNumber):
(JSC::FTL::LowerDFGToLLVM::initializeOSRExitStateForBlock):
(JSC::FTL::LowerDFGToLLVM::emitOSRExitCall):
(JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode):
(JSC::FTL::LowerDFGToLLVM::setInt52):
(JSC::FTL::LowerDFGToLLVM::setStrictInt52):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • ftl/FTLOutput.h:

(JSC::FTL::Output::addWithOverflow64):
(JSC::FTL::Output::subWithOverflow64):
(JSC::FTL::Output::mulWithOverflow64):

  • ftl/FTLValueFormat.cpp:

(WTF::printInternal):

  • ftl/FTLValueFormat.h:
  • ftl/FTLValueSource.cpp:

(JSC::FTL::ValueSource::dump):

  • ftl/FTLValueSource.h:
  • interpreter/Register.h:

(JSC::Register::unboxedInt52):

  • runtime/Arguments.cpp:

(JSC::Arguments::tearOffForInlineCallFrame):

  • runtime/IndexingType.cpp:

(JSC::leastUpperBoundOfIndexingTypeAndType):

  • runtime/JSCJSValue.h:
  • runtime/JSCJSValueInlines.h:

(JSC::JSValue::isMachineInt):
(JSC::JSValue::asMachineInt):

Source/WTF:

Reviewed by Oliver Hunt.

  • wtf/PrintStream.h:

(WTF::ValueIgnoringContext::ValueIgnoringContext):
(WTF::ValueIgnoringContext::dump):
(WTF::ignoringContext):

Tools:

Reviewed by Oliver Hunt.

  • Scripts/run-jsc-stress-tests:

LayoutTests:

Reviewed by Oliver Hunt.

  • js/regress/large-int-captured-expected.txt: Added.
  • js/regress/large-int-captured.html: Added.
  • js/regress/large-int-expected.txt: Added.
  • js/regress/large-int-neg-expected.txt: Added.
  • js/regress/large-int-neg.html: Added.
  • js/regress/large-int.html: Added.
  • js/regress/marsaglia-larger-ints-expected.txt: Added.
  • js/regress/marsaglia-larger-ints.html: Added.
  • js/regress/script-tests/large-int-captured.js: Added.

(.bar):
(foo):

  • js/regress/script-tests/large-int-neg.js: Added.

(foo):

  • js/regress/script-tests/large-int.js: Added.

(foo):

  • js/regress/script-tests/marsaglia-larger-ints.js: Added.

(uint):
(marsaglia):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r155783 r156019  
    160160    bool canReuse(Node* node)
    161161    {
    162         VirtualRegister virtualRegister = node->virtualRegister();
    163         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    164         return info.canReuse();
     162        return generationInfo(node).canReuse();
    165163    }
    166164    bool canReuse(Edge nodeUse)
     
    238236    bool isFilled(Node* node)
    239237    {
    240         VirtualRegister virtualRegister = node->virtualRegister();
    241         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    242         return info.registerFormat() != DataFormatNone;
     238        return generationInfo(node).registerFormat() != DataFormatNone;
    243239    }
    244240    bool isFilledDouble(Node* node)
    245241    {
    246         VirtualRegister virtualRegister = node->virtualRegister();
    247         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    248         return info.registerFormat() == DataFormatDouble;
     242        return generationInfo(node).registerFormat() == DataFormatDouble;
    249243    }
    250244
     
    254248        if (!node->hasResult())
    255249            return;
    256         VirtualRegister virtualRegister = node->virtualRegister();
    257         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
     250        GenerationInfo& info = generationInfo(node);
    258251
    259252        // use() returns true when the value becomes dead, and any
     
    334327    GPRReg fillSpeculateInt32(Edge, DataFormat& returnFormat);
    335328    GPRReg fillSpeculateInt32Strict(Edge);
     329    GPRReg fillSpeculateInt52(Edge, DataFormat desiredFormat);
    336330    FPRReg fillSpeculateDouble(Edge);
    337331    GPRReg fillSpeculateCell(Edge);
     
    469463        return boxDouble(fpr, allocate());
    470464    }
     465   
     466    void boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat);
    471467#elif USE(JSVALUE32_64)
    472468    void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
     
    560556    }
    561557   
    562     bool isKnownInteger(Node* node) { return !(m_state.forNode(node).m_type & ~SpecInt32); }
    563     bool isKnownCell(Node* node) { return !(m_state.forNode(node).m_type & ~SpecCell); }
     558    bool isKnownInteger(Node* node) { return m_state.forNode(node).isType(SpecInt32); }
     559    bool isKnownCell(Node* node) { return m_state.forNode(node).isType(SpecCell); }
    564560   
    565561    bool isKnownNotInteger(Node* node) { return !(m_state.forNode(node).m_type & SpecInt32); }
    566     bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecNumber); }
     562    bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecFullNumber); }
    567563    bool isKnownNotCell(Node* node) { return !(m_state.forNode(node).m_type & SpecCell); }
    568564   
     
    817813        int32Result(reg, node, DataFormatInt32, mode);
    818814    }
     815    void int52Result(GPRReg reg, Node* node, DataFormat format, UseChildrenMode mode = CallUseChildren)
     816    {
     817        if (mode == CallUseChildren)
     818            useChildren(node);
     819
     820        VirtualRegister virtualRegister = node->virtualRegister();
     821        GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
     822
     823        m_gprs.retain(reg, virtualRegister, SpillOrderJS);
     824        info.initInt52(node, node->refCount(), reg, format);
     825    }
     826    void int52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
     827    {
     828        int52Result(reg, node, DataFormatInt52, mode);
     829    }
     830    void strictInt52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
     831    {
     832        int52Result(reg, node, DataFormatStrictInt52, mode);
     833    }
    819834    void noResult(Node* node, UseChildrenMode mode = CallUseChildren)
    820835    {
     
    901916    {
    902917        ASSERT(isInt32Constant(node) || isNumberConstant(node) || isJSConstant(node));
    903         generationInfoFromVirtualRegister(node->virtualRegister()).initConstant(node, node->refCount());
     918        generationInfo(node).initConstant(node, node->refCount());
    904919    }
    905920   
     
    18901905            return true;
    18911906
    1892         VirtualRegister virtualRegister = node->virtualRegister();
    1893         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    1894        
    1895         return info.isJSInt32();
     1907        return generationInfo(node).isJSInt32();
     1908    }
     1909   
     1910    bool betterUseStrictInt52(Node* node)
     1911    {
     1912        return !generationInfo(node).isInt52();
     1913    }
     1914    bool betterUseStrictInt52(Edge edge)
     1915    {
     1916        return betterUseStrictInt52(edge.node());
    18961917    }
    18971918   
     
    18991920    bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
    19001921    void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
     1922    void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
    19011923    void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
    19021924    void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition);
     
    19461968   
    19471969    void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
     1970    void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
    19481971    void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition);
    19491972    void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
     
    21192142
    21202143    void speculateInt32(Edge);
     2144    void speculateMachineInt(Edge);
    21212145    void speculateNumber(Edge);
    21222146    void speculateRealNumber(Edge);
     
    21962220        return m_generationInfo[operandToLocal(virtualRegister)];
    21972221    }
     2222   
     2223    GenerationInfo& generationInfo(Node* node)
     2224    {
     2225        return generationInfoFromVirtualRegister(node->virtualRegister());
     2226    }
     2227   
     2228    GenerationInfo& generationInfo(Edge edge)
     2229    {
     2230        return generationInfo(edge.node());
     2231    }
    21982232
    21992233    // The JIT, while also provides MacroAssembler functionality.
     
    26772711};
    26782712
     2713// Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
     2714class SpeculateInt52Operand {
     2715public:
     2716    explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2717        : m_jit(jit)
     2718        , m_edge(edge)
     2719        , m_gprOrInvalid(InvalidGPRReg)
     2720    {
     2721        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2722        if (jit->isFilled(node()))
     2723            gpr();
     2724    }
     2725   
     2726    ~SpeculateInt52Operand()
     2727    {
     2728        ASSERT(m_gprOrInvalid != InvalidGPRReg);
     2729        m_jit->unlock(m_gprOrInvalid);
     2730    }
     2731   
     2732    Edge edge() const
     2733    {
     2734        return m_edge;
     2735    }
     2736   
     2737    Node* node() const
     2738    {
     2739        return edge().node();
     2740    }
     2741   
     2742    GPRReg gpr()
     2743    {
     2744        if (m_gprOrInvalid == InvalidGPRReg)
     2745            m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatInt52);
     2746        return m_gprOrInvalid;
     2747    }
     2748   
     2749    void use()
     2750    {
     2751        m_jit->use(node());
     2752    }
     2753   
     2754private:
     2755    SpeculativeJIT* m_jit;
     2756    Edge m_edge;
     2757    GPRReg m_gprOrInvalid;
     2758};
     2759
     2760// Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
     2761class SpeculateStrictInt52Operand {
     2762public:
     2763    explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2764        : m_jit(jit)
     2765        , m_edge(edge)
     2766        , m_gprOrInvalid(InvalidGPRReg)
     2767    {
     2768        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2769        if (jit->isFilled(node()))
     2770            gpr();
     2771    }
     2772   
     2773    ~SpeculateStrictInt52Operand()
     2774    {
     2775        ASSERT(m_gprOrInvalid != InvalidGPRReg);
     2776        m_jit->unlock(m_gprOrInvalid);
     2777    }
     2778   
     2779    Edge edge() const
     2780    {
     2781        return m_edge;
     2782    }
     2783   
     2784    Node* node() const
     2785    {
     2786        return edge().node();
     2787    }
     2788   
     2789    GPRReg gpr()
     2790    {
     2791        if (m_gprOrInvalid == InvalidGPRReg)
     2792            m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatStrictInt52);
     2793        return m_gprOrInvalid;
     2794    }
     2795   
     2796    void use()
     2797    {
     2798        m_jit->use(node());
     2799    }
     2800   
     2801private:
     2802    SpeculativeJIT* m_jit;
     2803    Edge m_edge;
     2804    GPRReg m_gprOrInvalid;
     2805};
     2806
     2807enum OppositeShiftTag { OppositeShift };
     2808
     2809class SpeculateWhicheverInt52Operand {
     2810public:
     2811    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2812        : m_jit(jit)
     2813        , m_edge(edge)
     2814        , m_gprOrInvalid(InvalidGPRReg)
     2815        , m_strict(jit->betterUseStrictInt52(edge))
     2816    {
     2817        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2818        if (jit->isFilled(node()))
     2819            gpr();
     2820    }
     2821   
     2822    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2823        : m_jit(jit)
     2824        , m_edge(edge)
     2825        , m_gprOrInvalid(InvalidGPRReg)
     2826        , m_strict(other.m_strict)
     2827    {
     2828        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2829        if (jit->isFilled(node()))
     2830            gpr();
     2831    }
     2832   
     2833    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2834        : m_jit(jit)
     2835        , m_edge(edge)
     2836        , m_gprOrInvalid(InvalidGPRReg)
     2837        , m_strict(!other.m_strict)
     2838    {
     2839        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2840        if (jit->isFilled(node()))
     2841            gpr();
     2842    }
     2843   
     2844    ~SpeculateWhicheverInt52Operand()
     2845    {
     2846        ASSERT(m_gprOrInvalid != InvalidGPRReg);
     2847        m_jit->unlock(m_gprOrInvalid);
     2848    }
     2849   
     2850    Edge edge() const
     2851    {
     2852        return m_edge;
     2853    }
     2854   
     2855    Node* node() const
     2856    {
     2857        return edge().node();
     2858    }
     2859   
     2860    GPRReg gpr()
     2861    {
     2862        if (m_gprOrInvalid == InvalidGPRReg) {
     2863            m_gprOrInvalid = m_jit->fillSpeculateInt52(
     2864                edge(), m_strict ? DataFormatStrictInt52 : DataFormatInt52);
     2865        }
     2866        return m_gprOrInvalid;
     2867    }
     2868   
     2869    void use()
     2870    {
     2871        m_jit->use(node());
     2872    }
     2873   
     2874    DataFormat format() const
     2875    {
     2876        return m_strict ? DataFormatStrictInt52 : DataFormatInt52;
     2877    }
     2878
     2879private:
     2880    SpeculativeJIT* m_jit;
     2881    Edge m_edge;
     2882    GPRReg m_gprOrInvalid;
     2883    bool m_strict;
     2884};
     2885
    26792886class SpeculateDoubleOperand {
    26802887public:
Note: See TracChangeset for help on using the changeset viewer.