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/ftl/FTLLowerDFGToLLVM.cpp

    r156016 r156019  
    152152                    type = m_out.int32;
    153153                    break;
     154                case NodeResultInt52:
     155                    type = m_out.int64;
     156                    break;
    154157                case NodeResultBoolean:
    155158                    type = m_out.boolean;
     
    240243            break;
    241244        case JSConstant:
    242             compileJSConstant();
    243245            break;
    244246        case WeakJSConstant:
     
    462464            m_out.set(lowInt32(m_node->child1()), destination);
    463465            break;
     466        case MachineIntUse:
     467            m_out.set(lowInt52(m_node->child1()), destination);
     468            break;
    464469        case BooleanUse:
    465470            m_out.set(lowBoolean(m_node->child1()), destination);
     
    487492        case NodeResultInt32:
    488493            setInt32(m_out.get(source));
     494            break;
     495        case NodeResultInt52:
     496            setInt52(m_out.get(source));
    489497            break;
    490498        case NodeResultBoolean:
     
    592600        }
    593601           
     602        case FlushedInt52: {
     603            LValue value = lowInt52(m_node->child1());
     604            m_out.store64(value, addressFor(variable->local()));
     605            m_valueSources.operand(variable->local()) = ValueSource(Int52InJSStack);
     606            return;
     607        }
     608           
    594609        case FlushedCell: {
    595610            LValue value = lowCell(m_node->child1());
     
    656671        }
    657672           
     673        case MachineIntUse: {
     674            if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
     675                && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
     676                Int52Kind kind;
     677                LValue left = lowWhicheverInt52(m_node->child1(), kind);
     678                LValue right = lowInt52(m_node->child2(), kind);
     679                setInt52(m_out.add(left, right), kind);
     680                break;
     681            }
     682           
     683            LValue left = lowInt52(m_node->child1());
     684            LValue right = lowInt52(m_node->child2());
     685            LValue result = m_out.addWithOverflow64(left, right);
     686            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
     687            setInt52(m_out.extractValue(result, 0));
     688            break;
     689        }
     690           
    658691        case NumberUse: {
    659692            setDouble(
     
    683716            speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
    684717            setInt32(m_out.extractValue(result, 0));
     718            break;
     719        }
     720           
     721        case MachineIntUse: {
     722            if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
     723                && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
     724                Int52Kind kind;
     725                LValue left = lowWhicheverInt52(m_node->child1(), kind);
     726                LValue right = lowInt52(m_node->child2(), kind);
     727                setInt52(m_out.sub(left, right), kind);
     728                break;
     729            }
     730           
     731            LValue left = lowInt52(m_node->child1());
     732            LValue right = lowInt52(m_node->child2());
     733            LValue result = m_out.subWithOverflow64(left, right);
     734            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
     735            setInt52(m_out.extractValue(result, 0));
    685736            break;
    686737        }
     
    728779           
    729780            setInt32(result);
     781            break;
     782        }
     783           
     784        case MachineIntUse: {
     785            Int52Kind kind;
     786            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     787            LValue right = lowInt52(m_node->child2(), opposite(kind));
     788           
     789            LValue overflowResult = m_out.mulWithOverflow64(left, right);
     790            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     791            LValue result = m_out.extractValue(overflowResult, 0);
     792           
     793            if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
     794                LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
     795                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
     796               
     797                m_out.branch(m_out.notZero64(result), continuation, slowCase);
     798               
     799                LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
     800                speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int64Zero));
     801                speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int64Zero));
     802                m_out.jump(continuation);
     803                m_out.appendTo(continuation, lastNext);
     804            }
     805           
     806            setInt52(result);
    730807            break;
    731808        }
     
    10301107           
    10311108            setInt32(result);
     1109            break;
     1110        }
     1111           
     1112        case MachineIntUse: {
     1113            if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) {
     1114                Int52Kind kind;
     1115                LValue value = lowWhicheverInt52(m_node->child1(), kind);
     1116                LValue result = m_out.neg(value);
     1117                if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags()))
     1118                    speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
     1119                setInt52(result, kind);
     1120                break;
     1121            }
     1122           
     1123            LValue value = lowInt52(m_node->child1());
     1124            LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
     1125            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     1126            LValue result = m_out.extractValue(overflowResult, 0);
     1127            speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
     1128            setInt52(result);
    10321129            break;
    10331130        }
     
    14741571               
    14751572                FTL_TYPE_CHECK(
    1476                     doubleValue(value), child3, SpecRealNumber,
     1573                    doubleValue(value), child3, SpecFullRealNumber,
    14771574                    m_out.doubleNotEqualOrUnordered(value, value));
    14781575               
     
    17091806    {
    17101807        if (m_node->isBinaryUseKind(Int32Use)
     1808            || m_node->isBinaryUseKind(MachineIntUse)
    17111809            || m_node->isBinaryUseKind(NumberUse)
    17121810            || m_node->isBinaryUseKind(ObjectUse)) {
     
    17321830            setBoolean(
    17331831                m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
     1832            return;
     1833        }
     1834       
     1835        if (m_node->isBinaryUseKind(MachineIntUse)) {
     1836            Int52Kind kind;
     1837            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     1838            LValue right = lowInt52(m_node->child2(), kind);
     1839            setBoolean(m_out.equal(left, right));
    17341840            return;
    17351841        }
     
    17831889        }
    17841890       
     1891        if (m_node->isBinaryUseKind(MachineIntUse)) {
     1892            Int52Kind kind;
     1893            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     1894            LValue right = lowInt52(m_node->child2(), kind);
     1895            setBoolean(m_out.lessThan(left, right));
     1896            return;
     1897        }
     1898       
    17851899        if (m_node->isBinaryUseKind(NumberUse)) {
    17861900            setBoolean(
     
    17971911            setBoolean(
    17981912                m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
     1913            return;
     1914        }
     1915       
     1916        if (m_node->isBinaryUseKind(MachineIntUse)) {
     1917            Int52Kind kind;
     1918            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     1919            LValue right = lowInt52(m_node->child2(), kind);
     1920            setBoolean(m_out.lessThanOrEqual(left, right));
    17991921            return;
    18001922        }
     
    18181940        }
    18191941       
     1942        if (m_node->isBinaryUseKind(MachineIntUse)) {
     1943            Int52Kind kind;
     1944            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     1945            LValue right = lowInt52(m_node->child2(), kind);
     1946            setBoolean(m_out.greaterThan(left, right));
     1947            return;
     1948        }
     1949       
    18201950        if (m_node->isBinaryUseKind(NumberUse)) {
    18211951            setBoolean(
     
    18341964                m_out.greaterThanOrEqual(
    18351965                    lowInt32(m_node->child1()), lowInt32(m_node->child2())));
     1966            return;
     1967        }
     1968       
     1969        if (m_node->isBinaryUseKind(MachineIntUse)) {
     1970            Int52Kind kind;
     1971            LValue left = lowWhicheverInt52(m_node->child1(), kind);
     1972            LValue right = lowInt52(m_node->child2(), kind);
     1973            setBoolean(m_out.greaterThanOrEqual(left, right));
    18361974            return;
    18371975        }
     
    23532491        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
    23542492       
     2493        if (edge->hasConstant()) {
     2494            JSValue value = m_graph.valueOfJSConstant(edge.node());
     2495            if (!value.isInt32()) {
     2496                terminate(Uncountable);
     2497                return m_out.int32Zero;
     2498            }
     2499            return m_out.constInt32(value.asInt32());
     2500        }
     2501       
    23552502        LoweredNodeValue value = m_int32Values.get(edge.node());
    23562503        if (isValid(value))
    23572504            return value.value();
     2505       
     2506        value = m_strictInt52Values.get(edge.node());
     2507        if (isValid(value))
     2508            return strictInt52ToInt32(edge, value.value());
     2509       
     2510        value = m_int52Values.get(edge.node());
     2511        if (isValid(value))
     2512            return strictInt52ToInt32(edge, int52ToStrictInt52(value.value()));
    23582513       
    23592514        value = m_jsValueValues.get(edge.node());
     
    23722527    }
    23732528   
     2529    enum Int52Kind { StrictInt52, Int52 };
     2530    LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2531    {
     2532        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
     2533       
     2534        if (edge->hasConstant()) {
     2535            JSValue value = m_graph.valueOfJSConstant(edge.node());
     2536            if (!value.isMachineInt()) {
     2537                terminate(Uncountable);
     2538                return m_out.int64Zero;
     2539            }
     2540            int64_t result = value.asMachineInt();
     2541            if (kind == Int52)
     2542                result <<= JSValue::int52ShiftAmount;
     2543            return m_out.constInt64(result);
     2544        }
     2545       
     2546        LoweredNodeValue value;
     2547       
     2548        switch (kind) {
     2549        case Int52:
     2550            value = m_int52Values.get(edge.node());
     2551            if (isValid(value))
     2552                return value.value();
     2553           
     2554            value = m_strictInt52Values.get(edge.node());
     2555            if (isValid(value))
     2556                return strictInt52ToInt52(value.value());
     2557            break;
     2558           
     2559        case StrictInt52:
     2560            value = m_strictInt52Values.get(edge.node());
     2561            if (isValid(value))
     2562                return value.value();
     2563           
     2564            value = m_int52Values.get(edge.node());
     2565            if (isValid(value))
     2566                return int52ToStrictInt52(value.value());
     2567            break;
     2568        }
     2569       
     2570        value = m_int32Values.get(edge.node());
     2571        if (isValid(value)) {
     2572            return setInt52WithStrictValue(
     2573                edge.node(), m_out.signExt(value.value(), m_out.int64), kind);
     2574        }
     2575       
     2576        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52));
     2577       
     2578        value = m_jsValueValues.get(edge.node());
     2579        if (isValid(value)) {
     2580            LValue boxedResult = value.value();
     2581            FTL_TYPE_CHECK(
     2582                jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult));
     2583            return setInt52WithStrictValue(
     2584                edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind);
     2585        }
     2586       
     2587        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt));
     2588        terminate(Uncountable);
     2589        return m_out.int64Zero;
     2590    }
     2591   
     2592    LValue lowInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2593    {
     2594        return lowInt52(edge, Int52, mode);
     2595    }
     2596   
     2597    LValue lowStrictInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2598    {
     2599        return lowInt52(edge, StrictInt52, mode);
     2600    }
     2601   
     2602    bool betterUseStrictInt52(Node* node)
     2603    {
     2604        return !isValid(m_int52Values.get(node));
     2605    }
     2606    bool betterUseStrictInt52(Edge edge)
     2607    {
     2608        return betterUseStrictInt52(edge.node());
     2609    }
     2610    template<typename T>
     2611    Int52Kind bestInt52Kind(T node)
     2612    {
     2613        return betterUseStrictInt52(node) ? StrictInt52 : Int52;
     2614    }
     2615    Int52Kind opposite(Int52Kind kind)
     2616    {
     2617        switch (kind) {
     2618        case Int52:
     2619            return StrictInt52;
     2620        case StrictInt52:
     2621            return Int52;
     2622        }
     2623        RELEASE_ASSERT_NOT_REACHED();
     2624    }
     2625   
     2626    LValue lowWhicheverInt52(Edge edge, Int52Kind& kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     2627    {
     2628        kind = bestInt52Kind(edge);
     2629        return lowInt52(edge, kind, mode);
     2630    }
     2631   
    23742632    LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
    23752633    {
    23762634        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
     2635       
     2636        if (edge->op() == JSConstant) {
     2637            JSValue value = m_graph.valueOfJSConstant(edge.node());
     2638            if (!value.isCell()) {
     2639                terminate(Uncountable);
     2640                return m_out.intPtrZero;
     2641            }
     2642            return m_out.constIntPtr(value.asCell());
     2643        }
    23772644       
    23782645        LoweredNodeValue value = m_jsValueValues.get(edge.node());
     
    24192686    {
    24202687        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
     2688       
     2689        if (edge->hasConstant()) {
     2690            JSValue value = m_graph.valueOfJSConstant(edge.node());
     2691            if (!value.isBoolean()) {
     2692                terminate(Uncountable);
     2693                return m_out.booleanFalse;
     2694            }
     2695            return m_out.constBool(value.asBoolean());
     2696        }
    24212697       
    24222698        LoweredNodeValue value = m_booleanValues.get(edge.node());
     
    24432719        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
    24442720       
     2721        if (edge->hasConstant()) {
     2722            JSValue value = m_graph.valueOfJSConstant(edge.node());
     2723            if (!value.isNumber()) {
     2724                terminate(Uncountable);
     2725                return m_out.doubleZero;
     2726            }
     2727            return m_out.constDouble(value.asNumber());
     2728        }
     2729       
    24452730        LoweredNodeValue value = m_doubleValues.get(edge.node());
    24462731        if (isValid(value))
     
    24542739        }
    24552740       
     2741        value = m_strictInt52Values.get(edge.node());
     2742        if (isValid(value))
     2743            return strictInt52ToDouble(edge, value.value());
     2744       
     2745        value = m_int52Values.get(edge.node());
     2746        if (isValid(value))
     2747            return strictInt52ToDouble(edge, int52ToStrictInt52(value.value()));
     2748       
    24562749        value = m_jsValueValues.get(edge.node());
    24572750        if (isValid(value)) {
     
    24732766           
    24742767            FTL_TYPE_CHECK(
    2475                 jsValueValue(boxedResult), edge, SpecNumber, isCellOrMisc(boxedResult));
     2768                jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult));
    24762769           
    24772770            ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
     
    24862779        }
    24872780       
    2488         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecNumber));
     2781        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber));
    24892782        terminate(Uncountable);
    24902783        return m_out.doubleZero;
     
    24942787    {
    24952788        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
     2789       
     2790        if (edge->hasConstant())
     2791            return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node())));
    24962792       
    24972793        LoweredNodeValue value = m_jsValueValues.get(edge.node());
     
    25062802        }
    25072803       
     2804        value = m_strictInt52Values.get(edge.node());
     2805        if (isValid(value))
     2806            return strictInt52ToJSValue(value.value());
     2807       
     2808        value = m_int52Values.get(edge.node());
     2809        if (isValid(value))
     2810            return strictInt52ToJSValue(int52ToStrictInt52(value.value()));
     2811       
    25082812        value = m_booleanValues.get(edge.node());
    25092813        if (isValid(value)) {
     
    25332837        setStorage(edge.node(), result);
    25342838        return result;
     2839    }
     2840   
     2841    LValue strictInt52ToInt32(Edge edge, LValue value)
     2842    {
     2843        LValue result = m_out.castToInt32(value);
     2844        FTL_TYPE_CHECK(
     2845            noValue(), edge, SpecInt32,
     2846            m_out.notEqual(m_out.signExt(result, m_out.int64), value));
     2847        setInt32(edge.node(), result);
     2848        return result;
     2849    }
     2850   
     2851    LValue strictInt52ToDouble(Edge edge, LValue value)
     2852    {
     2853        LValue result = m_out.intToDouble(value);
     2854        setDouble(edge.node(), result);
     2855        return result;
     2856    }
     2857   
     2858    LValue strictInt52ToJSValue(LValue value)
     2859    {
     2860        LBasicBlock isInt32 = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isInt32 case"));
     2861        LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isDouble case"));
     2862        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue continuation"));
     2863       
     2864        Vector<ValueFromBlock, 2> results;
     2865           
     2866        LValue int32Value = m_out.castToInt32(value);
     2867        m_out.branch(
     2868            m_out.equal(m_out.signExt(int32Value, m_out.int64), value),
     2869            isInt32, isDouble);
     2870       
     2871        LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble);
     2872       
     2873        results.append(m_out.anchor(boxInt32(int32Value)));
     2874        m_out.jump(continuation);
     2875       
     2876        m_out.appendTo(isDouble, continuation);
     2877       
     2878        results.append(m_out.anchor(boxDouble(m_out.intToDouble(value))));
     2879        m_out.jump(continuation);
     2880       
     2881        m_out.appendTo(continuation, lastNext);
     2882        return m_out.phi(m_out.int64, results);
     2883    }
     2884   
     2885    LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind)
     2886    {
     2887        switch (kind) {
     2888        case StrictInt52:
     2889            setStrictInt52(node, value);
     2890            return value;
     2891           
     2892        case Int52:
     2893            value = strictInt52ToInt52(value);
     2894            setInt52(node, value);
     2895            return value;
     2896        }
     2897       
     2898        RELEASE_ASSERT_NOT_REACHED();
     2899        return 0;
     2900    }
     2901
     2902    LValue strictInt52ToInt52(LValue value)
     2903    {
     2904        return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
     2905    }
     2906   
     2907    LValue int52ToStrictInt52(LValue value)
     2908    {
     2909        return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount));
    25352910    }
    25362911   
     
    27953170        LValue value = lowDouble(edge);
    27963171        FTL_TYPE_CHECK(
    2797             doubleValue(value), edge, SpecRealNumber,
     3172            doubleValue(value), edge, SpecFullRealNumber,
    27983173            m_out.doubleNotEqualOrUnordered(value, value));
    27993174    }
     
    28033178        lowBoolean(edge);
    28043179    }
    2805 
     3180   
    28063181    bool masqueradesAsUndefinedWatchpointIsStillValid()
    28073182    {
     
    29343309                break;
    29353310               
     3311            case FlushedInt52:
     3312                m_valueSources[i] = ValueSource(Int52InJSStack);
     3313                break;
     3314               
    29363315            case FlushedDouble:
    29373316                m_valueSources[i] = ValueSource(DoubleInJSStack);
     
    30363415            case Int32InJSStack:
    30373416                exit.m_values[i] = ExitValue::inJSStackAsInt32();
     3417                break;
     3418            case Int52InJSStack:
     3419                exit.m_values[i] = ExitValue::inJSStackAsInt52();
    30383420                break;
    30393421            case DoubleInJSStack:
     
    31403522        }
    31413523       
     3524        value = m_int52Values.get(node);
     3525        if (isValid(value)) {
     3526            addExitArgument(exit, arguments, index, ValueFormatInt52, value.value());
     3527            return;
     3528        }
     3529       
     3530        value = m_strictInt52Values.get(node);
     3531        if (isValid(value)) {
     3532            addExitArgument(exit, arguments, index, ValueFormatStrictInt52, value.value());
     3533            return;
     3534        }
     3535       
    31423536        value = m_booleanValues.get(node);
    31433537        if (isValid(value)) {
     
    32433637        m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
    32443638    }
     3639    void setInt52(Node* node, LValue value)
     3640    {
     3641        m_int52Values.set(node, LoweredNodeValue(value, m_highBlock));
     3642    }
     3643    void setStrictInt52(Node* node, LValue value)
     3644    {
     3645        m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock));
     3646    }
     3647    void setInt52(Node* node, LValue value, Int52Kind kind)
     3648    {
     3649        switch (kind) {
     3650        case Int52:
     3651            setInt52(node, value);
     3652            return;
     3653           
     3654        case StrictInt52:
     3655            setStrictInt52(node, value);
     3656            return;
     3657        }
     3658       
     3659        RELEASE_ASSERT_NOT_REACHED();
     3660    }
    32453661    void setJSValue(Node* node, LValue value)
    32463662    {
     
    32633679    {
    32643680        setInt32(m_node, value);
     3681    }
     3682    void setInt52(LValue value)
     3683    {
     3684        setInt52(m_node, value);
     3685    }
     3686    void setStrictInt52(LValue value)
     3687    {
     3688        setStrictInt52(m_node, value);
     3689    }
     3690    void setInt52(LValue value, Int52Kind kind)
     3691    {
     3692        setInt52(m_node, value, kind);
    32653693    }
    32663694    void setJSValue(LValue value)
     
    33433771   
    33443772    HashMap<Node*, LoweredNodeValue> m_int32Values;
     3773    HashMap<Node*, LoweredNodeValue> m_strictInt52Values;
     3774    HashMap<Node*, LoweredNodeValue> m_int52Values;
    33453775    HashMap<Node*, LoweredNodeValue> m_jsValueValues;
    33463776    HashMap<Node*, LoweredNodeValue> m_booleanValues;
Note: See TracChangeset for help on using the changeset viewer.