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

    r155593 r156019  
    6565        }
    6666       
     67        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
     68            fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex));
     69       
    6770        return true;
    6871    }
     
    9396        case SetLocal: {
    9497            // This gets handled by fixupSetLocalsInBlock().
    95             break;
     98            return;
    9699        }
    97100           
     
    125128            }
    126129           
     130            if (node->child1()->shouldSpeculateMachineInt()) {
     131                fixEdge<MachineIntUse>(node->child1());
     132                break;
     133            }
     134           
    127135            if (node->child1()->shouldSpeculateNumber()) {
    128136                fixEdge<NumberUse>(node->child1());
     
    198206                break;
    199207            }
     208            if (m_graph.negateShouldSpeculateMachineInt(node)) {
     209                fixEdge<MachineIntUse>(node->child1());
     210                break;
     211            }
    200212            fixEdge<NumberUse>(node->child1());
    201213            break;
     
    206218                fixEdge<Int32Use>(node->child1());
    207219                fixEdge<Int32Use>(node->child2());
     220                break;
     221            }
     222            if (m_graph.mulShouldSpeculateMachineInt(node)) {
     223                fixEdge<MachineIntUse>(node->child1());
     224                fixEdge<MachineIntUse>(node->child2());
    208225                break;
    209226            }
     
    301318                break;
    302319            }
     320            if (enableInt52()
     321                && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
     322                fixEdge<MachineIntUse>(node->child1());
     323                fixEdge<MachineIntUse>(node->child2());
     324                break;
     325            }
    303326            if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
    304327                fixEdge<NumberUse>(node->child1());
     
    354377                fixEdge<Int32Use>(node->child1());
    355378                fixEdge<Int32Use>(node->child2());
     379                break;
     380            }
     381            if (enableInt52()
     382                && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
     383                fixEdge<MachineIntUse>(node->child1());
     384                fixEdge<MachineIntUse>(node->child2());
    356385                break;
    357386            }
     
    477506                fixEdge<Int32Use>(child2);
    478507                fixEdge<Int32Use>(child3);
     508                if (child3->prediction() & SpecInt52)
     509                    fixEdge<MachineIntUse>(child3);
     510                else
     511                    fixEdge<Int32Use>(child3);
    479512                break;
    480513            case Array::Double:
     
    494527                if (child3->shouldSpeculateInt32())
    495528                    fixEdge<Int32Use>(child3);
     529                else if (child3->shouldSpeculateMachineInt())
     530                    fixEdge<MachineIntUse>(child3);
    496531                else
    497532                    fixEdge<NumberUse>(child3);
     
    848883        case CheckTierUpAtReturn:
    849884        case CheckTierUpAndOSREnter:
     885        case Int52ToDouble:
     886        case Int52ToValue:
    850887            RELEASE_ASSERT_NOT_REACHED();
    851888            break;
     
    11901227                fixEdge<Int32Use>(node->child1());
    11911228                break;
     1229            case FlushedInt52:
     1230                fixEdge<MachineIntUse>(node->child1());
     1231                break;
    11921232            case FlushedCell:
    11931233                fixEdge<CellUse>(node->child1());
     
    12001240                break;
    12011241            }
     1242        }
     1243        m_insertionSet.execute(block);
     1244    }
     1245   
     1246    void fixupUntypedSetLocalsInBlock(BasicBlock* block)
     1247    {
     1248        if (!block)
     1249            return;
     1250        ASSERT(block->isReachable);
     1251        m_block = block;
     1252        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
     1253            Node* node = m_currentNode = block->at(m_indexInBlock);
     1254            if (node->op() != SetLocal)
     1255                continue;
     1256           
     1257            if (node->child1().useKind() == UntypedUse)
     1258                fixEdge<UntypedUse>(node->child1());
    12021259        }
    12031260        m_insertionSet.execute(block);
     
    13051362            return;
    13061363       
     1364        // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
     1365        // https://bugs.webkit.org/show_bug.cgi?id=121518
     1366       
    13071367        VariableAccessData* variable = node->variableAccessData();
    13081368        switch (useKind) {
     
    13201380            if (alwaysUnboxSimplePrimitives()
    13211381                || isBooleanSpeculation(variable->prediction()))
     1382                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
     1383            break;
     1384        case MachineIntUse:
     1385            if (isMachineIntSpeculation(variable->prediction()))
    13221386                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
    13231387            break;
     
    13481412    void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
    13491413    {
    1350         if (isDouble(useKind) && edge->shouldSpeculateInt32ForArithmetic()) {
    1351             injectInt32ToDoubleNode(edge, useKind, direction);
     1414        if (isDouble(useKind)) {
     1415            if (edge->shouldSpeculateInt32ForArithmetic()) {
     1416                injectInt32ToDoubleNode(edge, useKind, direction);
     1417                return;
     1418            }
     1419           
     1420            if (enableInt52() && edge->shouldSpeculateMachineInt()) {
     1421                // Make all double uses of int52 values have an intermediate Int52ToDouble.
     1422                // This is for the same reason as Int52ToValue (see below) except that
     1423                // Int8ToDouble will convert int52's that fit in an int32 into a double
     1424                // rather than trying to create a boxed int32 like Int52ToValue does.
     1425               
     1426                Node* result = m_insertionSet.insertNode(
     1427                    m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
     1428                    m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
     1429                edge = Edge(result, useKind);
     1430                return;
     1431            }
     1432        }
     1433       
     1434        if (enableInt52() && useKind != MachineIntUse
     1435            && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
     1436            // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
     1437            // node to ensure that we handle this properly:
     1438            //
     1439            // a: SomeInt52
     1440            // b: ArithAdd(@a, ...)
     1441            // c: Call(..., @a)
     1442            // d: ArithAdd(@a, ...)
     1443            //
     1444            // Without an intermediate node and just labeling the uses, we will get:
     1445            //
     1446            // a: SomeInt52
     1447            // b: ArithAdd(Int52:@a, ...)
     1448            // c: Call(..., Untyped:@a)
     1449            // d: ArithAdd(Int52:@a, ...)
     1450            //
     1451            // And now the c->Untyped:@a edge will box the value of @a into a double. This
     1452            // is bad, because now the d->Int52:@a edge will either have to do double-to-int
     1453            // conversions, or will have to OSR exit unconditionally. Alternatively we could
     1454            // have the c->Untyped:@a edge box the value by copying rather than in-place.
     1455            // But these boxings are also costly so this wouldn't be great.
     1456            //
     1457            // The solution we use is to always have non-Int52 uses of predicted Int52's use
     1458            // an intervening Int52ToValue node:
     1459            //
     1460            // a: SomeInt52
     1461            // b: ArithAdd(Int52:@a, ...)
     1462            // x: Int52ToValue(Int52:@a)
     1463            // c: Call(..., Untyped:@x)
     1464            // d: ArithAdd(Int52:@a, ...)
     1465            //
     1466            // Note that even if we had multiple non-int52 uses of @a, the multiple
     1467            // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
     1468            // At the same time, @a would continue to be represented as a native int52.
     1469            //
     1470            // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
     1471            // int52's. This would have handled the above example but would fall over for:
     1472            //
     1473            // a: SomeInt52
     1474            // b: Call(..., @a)
     1475            // c: ArithAdd(@a, ...)
     1476            //
     1477            // But the solution we use handles the above gracefully.
     1478           
     1479            Node* result = m_insertionSet.insertNode(
     1480                m_indexInBlock, SpecInt52, Int52ToValue,
     1481                m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse));
     1482            edge = Edge(result, useKind);
    13521483            return;
    13531484        }
    13541485       
    13551486        observeUseKindOnNode<useKind>(edge.node());
     1487       
    13561488        edge.setUseKind(useKind);
    13571489    }
     
    13791511    {
    13801512        Node* result = m_insertionSet.insertNode(
    1381             m_indexInBlock, SpecInt48, Int32ToDouble,
     1513            m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
    13821514            m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
    13831515        if (direction == ForwardSpeculation)
     
    14351567    {
    14361568        AddSpeculationMode mode = m_graph.addSpeculationMode(node);
    1437         if (mode == DontSpeculateInt32)
    1438             return false;
    1439        
    1440         truncateConstantsIfNecessary(node, mode);
    1441         fixEdge<Int32Use>(node->child1());
    1442         fixEdge<Int32Use>(node->child2());
    1443         return true;
     1569        if (mode != DontSpeculateInt32) {
     1570            truncateConstantsIfNecessary(node, mode);
     1571            fixEdge<Int32Use>(node->child1());
     1572            fixEdge<Int32Use>(node->child2());
     1573            return true;
     1574        }
     1575       
     1576        if (m_graph.addShouldSpeculateMachineInt(node)) {
     1577            fixEdge<MachineIntUse>(node->child1());
     1578            fixEdge<MachineIntUse>(node->child2());
     1579            return true;
     1580        }
     1581       
     1582        return false;
    14441583    }
    14451584   
Note: See TracChangeset for help on using the changeset viewer.