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/DFGSpeculativeJIT64.cpp

    r155783 r156019  
    4141#if USE(JSVALUE64)
    4242
     43void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format)
     44{
     45    GPRReg tempGPR;
     46    if (sourceGPR == targetGPR)
     47        tempGPR = allocate();
     48    else
     49        tempGPR = targetGPR;
     50   
     51    FPRReg fpr = fprAllocate();
     52
     53    if (format == DataFormatInt52)
     54        m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
     55    else
     56        ASSERT(format == DataFormatStrictInt52);
     57   
     58    m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr);
     59   
     60    if (tempGPR != targetGPR)
     61        unlock(tempGPR);
     62   
     63    unlock(fpr);
     64}
     65
    4366GPRReg SpeculativeJIT::fillJSValue(Edge edge)
    4467{
     
    7093            DataFormat spillFormat = info.spillFormat();
    7194            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    72             if (spillFormat == DataFormatInt32) {
     95            switch (spillFormat) {
     96            case DataFormatInt32: {
    7397                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
    7498                m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
    7599                spillFormat = DataFormatJSInt32;
    76             } else {
     100                break;
     101            }
     102               
     103            case DataFormatInt52:
     104            case DataFormatStrictInt52: {
     105                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     106                boxInt52(gpr, gpr, spillFormat);
     107                return gpr;
     108            }
     109               
     110            default:
    77111                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
    78112                if (spillFormat == DataFormatDouble) {
     
    82116                } else
    83117                    RELEASE_ASSERT(spillFormat & DataFormatJS);
     118                break;
    84119            }
    85120            info.fillJSValue(*m_stream, gpr, spillFormat);
     
    113148
    114149        return gpr;
     150    }
     151       
     152    case DataFormatInt52:
     153    case DataFormatStrictInt52: {
     154        GPRReg gpr = info.gpr();
     155        lock(gpr);
     156        GPRReg resultGPR = allocate();
     157        boxInt52(gpr, resultGPR, info.registerFormat());
     158        unlock(gpr);
     159        return resultGPR;
    115160    }
    116161
     
    769814        DataFormat spillFormat = info.spillFormat();
    770815       
    771         RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
     816        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
    772817       
    773818        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     
    790835            return gpr;
    791836        }
     837        if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
     838            // Generally, this can only happen if we've already proved that the
     839            // value is an int32. That's because if a value originated as a JSValue
     840            // then we would speculate that it's an int32 before representing it as
     841            // an int52. Otherwise, if we knowingly produced an int52, then we would
     842            // be boxing it into a value using Int52ToValue. This assertion is valid
     843            // only because Int52 is something that we introduce at prediction time.
     844            // However: we may have an int32-producing node replaced by an
     845            // int52-producing node due to CSE. So we must do a check.
     846            RELEASE_ASSERT(!(type & ~SpecMachineInt));
     847            if (type & SpecInt52) {
     848                GPRReg temp = allocate();
     849                m_jit.signExtend32ToPtr(gpr, temp);
     850                // Currently, we can't supply value profiling information here. :-/
     851                speculationCheck(
     852                    BadType, JSValueRegs(), 0,
     853                    m_jit.branch64(MacroAssembler::NotEqual, gpr, temp));
     854                unlock(temp);
     855            }
     856            if (spillFormat == DataFormatStrictInt52)
     857                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
     858            else {
     859                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     860                m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     861                m_jit.zeroExtend32ToPtr(gpr, gpr);
     862            }
     863            info.fillInt32(*m_stream, gpr);
     864            returnFormat = DataFormatInt32;
     865            return gpr;
     866        }
    792867        m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
    793868
     
    798873
    799874    case DataFormatJS: {
     875        RELEASE_ASSERT(!(type & SpecInt52));
    800876        // Check the value is an integer.
    801877        GPRReg gpr = info.gpr();
     
    844920        return gpr;
    845921    }
     922       
     923    case DataFormatStrictInt52:
     924    case DataFormatInt52: {
     925        GPRReg gpr = info.gpr();
     926        GPRReg result;
     927        if (m_gprs.isLocked(gpr)) {
     928            result = allocate();
     929            m_jit.move(gpr, result);
     930        } else {
     931            lock(gpr);
     932            info.fillInt32(*m_stream, gpr);
     933            result = gpr;
     934        }
     935        RELEASE_ASSERT(!(type & ~SpecMachineInt));
     936        if (info.registerFormat() == DataFormatInt52)
     937            m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
     938        if (type & SpecInt52) {
     939            GPRReg temp = allocate();
     940            m_jit.signExtend32ToPtr(result, temp);
     941            // Currently, we can't supply value profiling information here. :-/
     942            speculationCheck(
     943                BadType, JSValueRegs(), 0,
     944                m_jit.branch64(MacroAssembler::NotEqual, result, temp));
     945            unlock(temp);
     946        }
     947        m_jit.zeroExtend32ToPtr(result, result);
     948        returnFormat = DataFormatInt32;
     949        return gpr;
     950    }
    846951
    847952    case DataFormatDouble:
     
    886991}
    887992
     993GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
     994{
     995    ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
     996    AbstractValue& value = m_state.forNode(edge);
     997    SpeculatedType type = value.m_type;
     998    m_interpreter.filter(value, SpecMachineInt);
     999    VirtualRegister virtualRegister = edge->virtualRegister();
     1000    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
     1001
     1002    switch (info.registerFormat()) {
     1003    case DataFormatNone: {
     1004        if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) {
     1005            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
     1006            return allocate();
     1007        }
     1008       
     1009        GPRReg gpr = allocate();
     1010
     1011        if (edge->hasConstant()) {
     1012            JSValue jsValue = valueOfJSConstant(edge.node());
     1013            ASSERT(jsValue.isMachineInt());
     1014            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
     1015            int64_t value = jsValue.asMachineInt();
     1016            if (desiredFormat == DataFormatInt52)
     1017                value = value << JSValue::int52ShiftAmount;
     1018            m_jit.move(MacroAssembler::Imm64(value), gpr);
     1019            info.fillGPR(*m_stream, gpr, desiredFormat);
     1020            return gpr;
     1021        }
     1022       
     1023        DataFormat spillFormat = info.spillFormat();
     1024       
     1025        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
     1026       
     1027        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     1028       
     1029        if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
     1030            // If we know this was spilled as an integer we can fill without checking.
     1031            m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
     1032            m_jit.signExtend32ToPtr(gpr, gpr);
     1033            if (desiredFormat == DataFormatStrictInt52) {
     1034                info.fillStrictInt52(*m_stream, gpr);
     1035                return gpr;
     1036            }
     1037            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     1038            info.fillInt52(*m_stream, gpr);
     1039            return gpr;
     1040        }
     1041        if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
     1042            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     1043            if (desiredFormat == DataFormatStrictInt52) {
     1044                if (spillFormat == DataFormatInt52)
     1045                    m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     1046                info.fillStrictInt52(*m_stream, gpr);
     1047                return gpr;
     1048            }
     1049            if (spillFormat == DataFormatStrictInt52)
     1050                m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     1051            info.fillInt52(*m_stream, gpr);
     1052            return gpr;
     1053        }
     1054        m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     1055
     1056        // Fill as JSValue, and fall through.
     1057        info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
     1058        m_gprs.unlock(gpr);
     1059    }
     1060
     1061    case DataFormatJS: {
     1062        // Check the value is an integer. Note that we would *like* to unbox an Int52
     1063        // at this point but this is too costly. We only *prove* that this is an Int52
     1064        // even though we check if it's an int32.
     1065        GPRReg gpr = info.gpr();
     1066        GPRReg result;
     1067        if (m_gprs.isLocked(gpr)) {
     1068            result = allocate();
     1069            m_jit.move(gpr, result);
     1070        } else {
     1071            m_gprs.lock(gpr);
     1072            result = gpr;
     1073        }
     1074        if (type & ~SpecInt32)
     1075            speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister));
     1076        if (result == gpr) // The not-already-locked, so fill in-place, case.
     1077            info.fillInt52(*m_stream, gpr, desiredFormat);
     1078        m_jit.signExtend32ToPtr(result, result);
     1079        if (desiredFormat == DataFormatInt52)
     1080            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
     1081        return result;
     1082    }
     1083
     1084    case DataFormatInt32:
     1085    case DataFormatJSInt32: {
     1086        GPRReg gpr = info.gpr();
     1087        GPRReg result;
     1088        if (m_gprs.isLocked(gpr)) {
     1089            result = allocate();
     1090            m_jit.move(gpr, result);
     1091        } else {
     1092            m_gprs.lock(gpr);
     1093            info.fillInt52(*m_stream, gpr, desiredFormat);
     1094            result = gpr;
     1095        }
     1096        m_jit.signExtend32ToPtr(result, result);
     1097        if (desiredFormat == DataFormatInt52)
     1098            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
     1099        return result;
     1100    }
     1101
     1102    case DataFormatStrictInt52: {
     1103        GPRReg gpr = info.gpr();
     1104        bool wasLocked = m_gprs.isLocked(gpr);
     1105        lock(gpr);
     1106        if (desiredFormat == DataFormatStrictInt52)
     1107            return gpr;
     1108        if (wasLocked) {
     1109            GPRReg result = allocate();
     1110            m_jit.move(gpr, result);
     1111            unlock(gpr);
     1112            gpr = result;
     1113        } else
     1114            info.fillStrictInt52(*m_stream, gpr);
     1115        m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     1116        return gpr;
     1117    }
     1118       
     1119    case DataFormatInt52: {
     1120        GPRReg gpr = info.gpr();
     1121        bool wasLocked = m_gprs.isLocked(gpr);
     1122        lock(gpr);
     1123        if (desiredFormat == DataFormatInt52)
     1124            return gpr;
     1125        if (wasLocked) {
     1126            GPRReg result = allocate();
     1127            m_jit.move(gpr, result);
     1128            unlock(gpr);
     1129            gpr = result;
     1130        } else
     1131            info.fillInt52(*m_stream, gpr);
     1132        m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
     1133        return gpr;
     1134    }
     1135
     1136    case DataFormatDouble:
     1137    case DataFormatJSDouble:
     1138        if (edge->hasConstant()) {
     1139            JSValue jsValue = valueOfJSConstant(edge.node());
     1140            if (jsValue.isMachineInt()) {
     1141                int64_t value = jsValue.asMachineInt();
     1142                if (desiredFormat == DataFormatInt52)
     1143                    value = value << JSValue::int52ShiftAmount;
     1144                GPRReg gpr = allocate();
     1145                m_jit.move(MacroAssembler::Imm64(value), gpr);
     1146                return gpr;
     1147            }
     1148        }
     1149       
     1150    case DataFormatCell:
     1151    case DataFormatBoolean:
     1152    case DataFormatJSCell:
     1153    case DataFormatJSBoolean: {
     1154        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
     1155        return allocate();
     1156    }
     1157
     1158    case DataFormatStorage:
     1159        RELEASE_ASSERT_NOT_REACHED();
     1160       
     1161    default:
     1162        RELEASE_ASSERT_NOT_REACHED();
     1163        return InvalidGPRReg;
     1164    }
     1165}
     1166
    8881167FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
    8891168{
     
    8931172    AbstractValue& value = m_state.forNode(edge);
    8941173    SpeculatedType type = value.m_type;
    895     ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecNumber));
    896     m_interpreter.filter(value, SpecNumber);
     1174    ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
     1175    m_interpreter.filter(value, SpecFullNumber);
    8971176    VirtualRegister virtualRegister = edge->virtualRegister();
    8981177    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
     
    9461225            break;
    9471226        }
     1227           
     1228        case DataFormatInt52: {
     1229            GPRReg gpr = allocate();
     1230            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     1231            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     1232            info.fillInt52(*m_stream, gpr);
     1233            unlock(gpr);
     1234            break;
     1235        }
     1236           
     1237        case DataFormatStrictInt52: {
     1238            GPRReg gpr = allocate();
     1239            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     1240            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     1241            info.fillStrictInt52(*m_stream, gpr);
     1242            unlock(gpr);
     1243            break;
     1244        }
    9481245
    9491246        default:
     
    9791276        JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    9801277
    981         if (type & ~SpecNumber)
     1278        if (type & ~SpecFullNumber)
    9821279            speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
    9831280
     
    10071304        m_gprs.lock(gpr);
    10081305        m_jit.convertInt32ToDouble(gpr, fpr);
     1306        m_gprs.unlock(gpr);
     1307        return fpr;
     1308    }
     1309       
     1310    case DataFormatInt52: {
     1311        FPRReg fpr = fprAllocate();
     1312        GPRReg gpr = info.gpr();
     1313        m_gprs.lock(gpr);
     1314        GPRReg temp = allocate();
     1315        m_jit.move(gpr, temp);
     1316        m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp);
     1317        m_jit.convertInt64ToDouble(temp, fpr);
     1318        unlock(temp);
     1319        m_gprs.unlock(gpr);
     1320        return fpr;
     1321    }
     1322       
     1323    case DataFormatStrictInt52: {
     1324        FPRReg fpr = fprAllocate();
     1325        GPRReg gpr = info.gpr();
     1326        m_gprs.lock(gpr);
     1327        m_jit.convertInt64ToDouble(gpr, fpr);
    10091328        m_gprs.unlock(gpr);
    10101329        return fpr;
     
    11121431    case DataFormatDouble:
    11131432    case DataFormatJSBoolean:
    1114     case DataFormatBoolean: {
     1433    case DataFormatBoolean:
     1434    case DataFormatInt52:
     1435    case DataFormatStrictInt52: {
    11151436        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    11161437        return allocate();
     
    11951516    case DataFormatDouble:
    11961517    case DataFormatJSCell:
    1197     case DataFormatCell: {
     1518    case DataFormatCell:
     1519    case DataFormatInt52:
     1520    case DataFormatStrictInt52: {
    11981521        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    11991522        return allocate();
     
    15021825    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    15031826    jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
     1827}
     1828
     1829void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
     1830{
     1831    SpeculateWhicheverInt52Operand op1(this, node->child1());
     1832    SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
     1833    GPRTemporary result(this, Reuse, op1, op2);
     1834   
     1835    m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
     1836   
     1837    // If we add a DataFormatBool, we should use it here.
     1838    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
     1839    jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
     1840}
     1841
     1842void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
     1843{
     1844    BasicBlock* taken = branchNode->takenBlock();
     1845    BasicBlock* notTaken = branchNode->notTakenBlock();
     1846
     1847    // The branch instruction will branch to the taken block.
     1848    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
     1849    if (taken == nextBlock()) {
     1850        condition = JITCompiler::invert(condition);
     1851        BasicBlock* tmp = taken;
     1852        taken = notTaken;
     1853        notTaken = tmp;
     1854    }
     1855   
     1856    SpeculateWhicheverInt52Operand op1(this, node->child1());
     1857    SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
     1858   
     1859    branch64(condition, op1.gpr(), op2.gpr(), taken);
     1860    jump(notTaken);
    15041861}
    15051862
     
    19072264        }
    19082265           
     2266        case FlushedInt52: {
     2267            GPRTemporary result(this);
     2268            m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr());
     2269           
     2270            VirtualRegister virtualRegister = node->virtualRegister();
     2271            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
     2272            generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
     2273            break;
     2274        }
     2275           
    19092276        default:
    19102277            GPRTemporary result(this);
     
    19822349        }
    19832350           
     2351        case FlushedInt52: {
     2352            SpeculateInt52Operand value(this, node->child1());
     2353            m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
     2354            noResult(node);
     2355            recordSetLocal(node->local(), ValueSource(Int52InJSStack));
     2356            break;
     2357        }
     2358           
    19842359        case FlushedCell: {
    19852360            SpeculateCellOperand cell(this, node->child1());
     
    21022477    case Int32ToDouble: {
    21032478        compileInt32ToDouble(node);
     2479        break;
     2480    }
     2481       
     2482    case Int52ToValue: {
     2483        JSValueOperand operand(this, node->child1());
     2484        GPRTemporary result(this, Reuse, operand);
     2485        m_jit.move(operand.gpr(), result.gpr());
     2486        jsValueResult(result.gpr(), node);
     2487        break;
     2488    }
     2489       
     2490    case Int52ToDouble: {
     2491        SpeculateDoubleOperand operand(this, node->child1());
     2492        FPRTemporary result(this, operand);
     2493        m_jit.moveDouble(operand.fpr(), result.fpr());
     2494        doubleResult(result.fpr(), node);
    21042495        break;
    21052496    }
     
    28903281
    28913282            DFG_TYPE_CHECK(
    2892                 JSValueRegs(), node->child2(), SpecRealNumber,
     3283                JSValueRegs(), node->child2(), SpecFullRealNumber,
    28933284                m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
    28943285           
     
    31063497        op1.use();
    31073498       
    3108         if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean)))
     3499        if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean)))
    31093500            m_jit.move(op1GPR, resultGPR);
    31103501        else {
     
    32033594                    FPRReg opFPR = operand.fpr();
    32043595                    DFG_TYPE_CHECK(
    3205                         JSValueRegs(), use, SpecRealNumber,
     3596                        JSValueRegs(), use, SpecFullRealNumber,
    32063597                        m_jit.branchDouble(
    32073598                            MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
     
    32683659                GPRReg scratchGPR = scratch.gpr();
    32693660                DFG_TYPE_CHECK(
    3270                     JSValueRegs(), use, SpecRealNumber,
     3661                    JSValueRegs(), use, SpecFullRealNumber,
    32713662                    m_jit.branchDouble(
    32723663                        MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
Note: See TracChangeset for help on using the changeset viewer.