DFG IR should keep the data flow of doubles and int52's separate from the data flow...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Apr 2014 20:26:16 +0000 (20:26 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Apr 2014 20:26:16 +0000 (20:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131423

Reviewed by Geoffrey Garen.

This introduces more static typing into DFG IR. Previously we just had the notion of
JSValues and Storage. This was weird because doubles weren't always convertible to
JSValues, and Int52s weren't always convertible to either doubles or JSValues. We would
sort of insert explicit conversion nodes just for the places where we knew that an
implicit conversion wouldn't have been possible -- but there was no hard and fast rule so
we'd get bugs from forgetting to do the right conversion.

This patch introduces a hard and fast rule: doubles can never be implicitly converted to
anything but doubles, and likewise Int52's can never be implicitly converted. Conversion
nodes are used for all of the conversions. Int52Rep, DoubleRep, and ValueRep are the
conversions. They are like Identity but return the same value using a different
representation. Likewise, constants may now be represented using either JSConstant,
Int52Constant, or DoubleConstant. UseKinds have been adjusted accordingly, as well.
Int52RepUse and DoubleRepUse are node uses that mean "the node must be of Int52 (or
Double) type". They don't imply checks. There is also DoubleRepRealUse, which means that
we speculate DoubleReal and expect Double representation.

In addition to simplifying a bunch of rules in the IR and making the IR more verifiable,
this also makes it easier to introduce optimizations in the future. It's now possible for
AI to model when/how conversion take place. For example if doing a conversion results in
NaN sanitization, then AI can model this and can allow us to sink sanitizations. That's
what https://bugs.webkit.org/show_bug.cgi?id=131419 will be all about.

This was a big change, so I had to do some interesting things, like finally get rid of
the DFG's weird variadic template macro hacks and use real C++11 variadic templates. Also
the ByteCodeParser no longer emits Identity nodes since that was always pointless.

No performance change because this mostly just rationalizes preexisting behavior.

* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerX86.h:
* bytecode/CodeBlock.cpp:
* bytecode/CodeBlock.h:
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::setBuiltInConstant):
(JSC::DFG::AbstractInterpreter::setConstant):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::fixTypeForRepresentation):
(JSC::DFG::AbstractValue::checkConsistency):
* dfg/DFGAbstractValue.h:
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGBasicBlock.h:
* dfg/DFGBasicBlockInlines.h:
(JSC::DFG::BasicBlock::appendNode):
(JSC::DFG::BasicBlock::appendNonTerminal):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::constantCSE):
(JSC::DFG::CSEPhase::performNodeCSE):
(JSC::DFG::CSEPhase::int32ToDoubleCSE): Deleted.
* dfg/DFGCapabilities.h:
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::fixupBlock):
* dfg/DFGEdge.h:
(JSC::DFG::Edge::willNotHaveCheck):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::run):
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupGetAndSetLocalsInBlock):
(JSC::DFG::FixupPhase::observeUseKindOnNode):
(JSC::DFG::FixupPhase::fixIntEdge):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
(JSC::DFG::FixupPhase::injectTypeConversionsInBlock):
(JSC::DFG::FixupPhase::tryToRelaxRepresentation):
(JSC::DFG::FixupPhase::fixEdgeRepresentation):
(JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
(JSC::DFG::FixupPhase::addRequiredPhantom):
(JSC::DFG::FixupPhase::addPhantomsIfNecessary):
(JSC::DFG::FixupPhase::clearPhantomsAtEnd):
(JSC::DFG::FixupPhase::fixupSetLocalsInBlock): Deleted.
* dfg/DFGFlushFormat.h:
(JSC::DFG::resultFor):
(JSC::DFG::useKindFor):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::addNode):
* dfg/DFGInPlaceAbstractState.cpp:
(JSC::DFG::InPlaceAbstractState::initialize):
* dfg/DFGInsertionSet.h:
(JSC::DFG::InsertionSet::insertNode):
(JSC::DFG::InsertionSet::insertConstant):
(JSC::DFG::InsertionSet::insertConstantForUse):
* dfg/DFGIntegerCheckCombiningPhase.cpp:
(JSC::DFG::IntegerCheckCombiningPhase::insertAdd):
(JSC::DFG::IntegerCheckCombiningPhase::insertMustAdd):
* dfg/DFGNode.cpp:
(JSC::DFG::Node::convertToIdentity):
(WTF::printInternal):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::setResult):
(JSC::DFG::Node::result):
(JSC::DFG::Node::isConstant):
(JSC::DFG::Node::hasConstant):
(JSC::DFG::Node::convertToConstant):
(JSC::DFG::Node::valueOfJSConstant):
(JSC::DFG::Node::hasResult):
(JSC::DFG::Node::hasInt32Result):
(JSC::DFG::Node::hasInt52Result):
(JSC::DFG::Node::hasNumberResult):
(JSC::DFG::Node::hasDoubleResult):
(JSC::DFG::Node::hasJSResult):
(JSC::DFG::Node::hasBooleanResult):
(JSC::DFG::Node::hasStorageResult):
(JSC::DFG::Node::defaultUseKind):
(JSC::DFG::Node::defaultEdge):
(JSC::DFG::Node::convertToIdentity): Deleted.
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::dumpNodeFlags):
* dfg/DFGNodeFlags.h:
(JSC::DFG::canonicalResultRepresentation):
* dfg/DFGNodeType.h:
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGResurrectionForValidationPhase.cpp:
(JSC::DFG::ResurrectionForValidationPhase::run):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
(JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
(JSC::DFG::SpeculativeJIT::silentFill):
(JSC::DFG::JSValueRegsTemporary::JSValueRegsTemporary):
(JSC::DFG::JSValueRegsTemporary::~JSValueRegsTemporary):
(JSC::DFG::JSValueRegsTemporary::regs):
(JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
(JSC::DFG::SpeculativeJIT::checkGeneratedTypeForToInt32):
(JSC::DFG::SpeculativeJIT::compileValueToInt32):
(JSC::DFG::SpeculativeJIT::compileDoubleRep):
(JSC::DFG::SpeculativeJIT::compileValueRep):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileAdd):
(JSC::DFG::SpeculativeJIT::compileArithSub):
(JSC::DFG::SpeculativeJIT::compileArithNegate):
(JSC::DFG::SpeculativeJIT::compileArithMul):
(JSC::DFG::SpeculativeJIT::compileArithDiv):
(JSC::DFG::SpeculativeJIT::compileArithMod):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::speculateNumber):
(JSC::DFG::SpeculativeJIT::speculateDoubleReal):
(JSC::DFG::SpeculativeJIT::speculate):
(JSC::DFG::SpeculativeJIT::compileInt32ToDouble): Deleted.
(JSC::DFG::SpeculativeJIT::speculateMachineInt): Deleted.
(JSC::DFG::SpeculativeJIT::speculateRealNumber): Deleted.
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::allocate):
(JSC::DFG::SpeculativeJIT::use):
(JSC::DFG::SpeculativeJIT::boxDouble):
(JSC::DFG::SpeculativeJIT::spill):
(JSC::DFG::SpeculativeJIT::jsValueResult):
(JSC::DFG::SpeculateInt52Operand::SpeculateInt52Operand):
(JSC::DFG::SpeculateStrictInt52Operand::SpeculateStrictInt52Operand):
(JSC::DFG::SpeculateWhicheverInt52Operand::SpeculateWhicheverInt52Operand):
(JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::fillJSValue):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::convertToDouble): Deleted.
* dfg/DFGSpeculativeJIT64.cpp:
(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::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::convertToDouble): Deleted.
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
(JSC::DFG::shouldNotHaveTypeCheck):
(JSC::DFG::mayHaveTypeCheck):
(JSC::DFG::isNumerical):
(JSC::DFG::isDouble):
(JSC::DFG::isCell):
(JSC::DFG::usesStructure):
(JSC::DFG::useKindForResult):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
* dfg/DFGVariadicFunction.h: Removed.
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::createPhiVariables):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileUpsilon):
(JSC::FTL::LowerDFGToLLVM::compilePhi):
(JSC::FTL::LowerDFGToLLVM::compileDoubleConstant):
(JSC::FTL::LowerDFGToLLVM::compileInt52Constant):
(JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant):
(JSC::FTL::LowerDFGToLLVM::compileDoubleRep):
(JSC::FTL::LowerDFGToLLVM::compileValueRep):
(JSC::FTL::LowerDFGToLLVM::compileInt52Rep):
(JSC::FTL::LowerDFGToLLVM::compileValueToInt32):
(JSC::FTL::LowerDFGToLLVM::compileArithAddOrSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithDiv):
(JSC::FTL::LowerDFGToLLVM::compileArithMod):
(JSC::FTL::LowerDFGToLLVM::compileArithMinOrMax):
(JSC::FTL::LowerDFGToLLVM::compileArithAbs):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::compileCompareEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
(JSC::FTL::LowerDFGToLLVM::compare):
(JSC::FTL::LowerDFGToLLVM::boolify):
(JSC::FTL::LowerDFGToLLVM::lowInt52):
(JSC::FTL::LowerDFGToLLVM::lowStrictInt52):
(JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52):
(JSC::FTL::LowerDFGToLLVM::lowDouble):
(JSC::FTL::LowerDFGToLLVM::lowJSValue):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToDouble):
(JSC::FTL::LowerDFGToLLVM::jsValueToDouble):
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateNumber):
(JSC::FTL::LowerDFGToLLVM::speculateDoubleReal):
(JSC::FTL::LowerDFGToLLVM::compileInt52ToValue): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble): Deleted.
(JSC::FTL::LowerDFGToLLVM::setInt52WithStrictValue): Deleted.
(JSC::FTL::LowerDFGToLLVM::speculateRealNumber): Deleted.
(JSC::FTL::LowerDFGToLLVM::speculateMachineInt): Deleted.
* ftl/FTLValueFormat.cpp:
(JSC::FTL::reboxAccordingToFormat):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::sanitizeDouble):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::boxDouble):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@167325 268f45cc-cd09-0410-ab3c-d52691b4dbfc

51 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/assembler/MacroAssemblerX86.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGBasicBlock.h
Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.h
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
Source/JavaScriptCore/dfg/DFGEdge.h
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGFlushFormat.h
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
Source/JavaScriptCore/dfg/DFGInsertionSet.h
Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp
Source/JavaScriptCore/dfg/DFGNode.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
Source/JavaScriptCore/dfg/DFGNodeFlags.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGResurrectionForValidationPhase.cpp
Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
Source/JavaScriptCore/dfg/DFGUseKind.cpp
Source/JavaScriptCore/dfg/DFGUseKind.h
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/dfg/DFGVariadicFunction.h [deleted file]
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLValueFormat.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.h

index 53f1c4f..c4c0c03 100644 (file)
@@ -1,3 +1,268 @@
+2014-04-15  Filip Pizlo  <fpizlo@apple.com>
+
+        DFG IR should keep the data flow of doubles and int52's separate from the data flow of JSValue's
+        https://bugs.webkit.org/show_bug.cgi?id=131423
+
+        Reviewed by Geoffrey Garen.
+        
+        This introduces more static typing into DFG IR. Previously we just had the notion of
+        JSValues and Storage. This was weird because doubles weren't always convertible to
+        JSValues, and Int52s weren't always convertible to either doubles or JSValues. We would
+        sort of insert explicit conversion nodes just for the places where we knew that an
+        implicit conversion wouldn't have been possible -- but there was no hard and fast rule so
+        we'd get bugs from forgetting to do the right conversion.
+        
+        This patch introduces a hard and fast rule: doubles can never be implicitly converted to
+        anything but doubles, and likewise Int52's can never be implicitly converted. Conversion
+        nodes are used for all of the conversions. Int52Rep, DoubleRep, and ValueRep are the
+        conversions. They are like Identity but return the same value using a different
+        representation. Likewise, constants may now be represented using either JSConstant,
+        Int52Constant, or DoubleConstant. UseKinds have been adjusted accordingly, as well.
+        Int52RepUse and DoubleRepUse are node uses that mean "the node must be of Int52 (or
+        Double) type". They don't imply checks. There is also DoubleRepRealUse, which means that
+        we speculate DoubleReal and expect Double representation.
+        
+        In addition to simplifying a bunch of rules in the IR and making the IR more verifiable,
+        this also makes it easier to introduce optimizations in the future. It's now possible for
+        AI to model when/how conversion take place. For example if doing a conversion results in
+        NaN sanitization, then AI can model this and can allow us to sink sanitizations. That's
+        what https://bugs.webkit.org/show_bug.cgi?id=131419 will be all about.
+        
+        This was a big change, so I had to do some interesting things, like finally get rid of
+        the DFG's weird variadic template macro hacks and use real C++11 variadic templates. Also
+        the ByteCodeParser no longer emits Identity nodes since that was always pointless.
+        
+        No performance change because this mostly just rationalizes preexisting behavior.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerX86.h:
+        * bytecode/CodeBlock.cpp:
+        * bytecode/CodeBlock.h:
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::setBuiltInConstant):
+        (JSC::DFG::AbstractInterpreter::setConstant):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::set):
+        (JSC::DFG::AbstractValue::fixTypeForRepresentation):
+        (JSC::DFG::AbstractValue::checkConsistency):
+        * dfg/DFGAbstractValue.h:
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+        * dfg/DFGBasicBlock.h:
+        * dfg/DFGBasicBlockInlines.h:
+        (JSC::DFG::BasicBlock::appendNode):
+        (JSC::DFG::BasicBlock::appendNonTerminal):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::constantCSE):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        (JSC::DFG::CSEPhase::int32ToDoubleCSE): Deleted.
+        * dfg/DFGCapabilities.h:
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::fixupBlock):
+        * dfg/DFGEdge.h:
+        (JSC::DFG::Edge::willNotHaveCheck):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::run):
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupGetAndSetLocalsInBlock):
+        (JSC::DFG::FixupPhase::observeUseKindOnNode):
+        (JSC::DFG::FixupPhase::fixIntEdge):
+        (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
+        (JSC::DFG::FixupPhase::injectTypeConversionsInBlock):
+        (JSC::DFG::FixupPhase::tryToRelaxRepresentation):
+        (JSC::DFG::FixupPhase::fixEdgeRepresentation):
+        (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
+        (JSC::DFG::FixupPhase::addRequiredPhantom):
+        (JSC::DFG::FixupPhase::addPhantomsIfNecessary):
+        (JSC::DFG::FixupPhase::clearPhantomsAtEnd):
+        (JSC::DFG::FixupPhase::fixupSetLocalsInBlock): Deleted.
+        * dfg/DFGFlushFormat.h:
+        (JSC::DFG::resultFor):
+        (JSC::DFG::useKindFor):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::addNode):
+        * dfg/DFGInPlaceAbstractState.cpp:
+        (JSC::DFG::InPlaceAbstractState::initialize):
+        * dfg/DFGInsertionSet.h:
+        (JSC::DFG::InsertionSet::insertNode):
+        (JSC::DFG::InsertionSet::insertConstant):
+        (JSC::DFG::InsertionSet::insertConstantForUse):
+        * dfg/DFGIntegerCheckCombiningPhase.cpp:
+        (JSC::DFG::IntegerCheckCombiningPhase::insertAdd):
+        (JSC::DFG::IntegerCheckCombiningPhase::insertMustAdd):
+        * dfg/DFGNode.cpp:
+        (JSC::DFG::Node::convertToIdentity):
+        (WTF::printInternal):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::Node):
+        (JSC::DFG::Node::setResult):
+        (JSC::DFG::Node::result):
+        (JSC::DFG::Node::isConstant):
+        (JSC::DFG::Node::hasConstant):
+        (JSC::DFG::Node::convertToConstant):
+        (JSC::DFG::Node::valueOfJSConstant):
+        (JSC::DFG::Node::hasResult):
+        (JSC::DFG::Node::hasInt32Result):
+        (JSC::DFG::Node::hasInt52Result):
+        (JSC::DFG::Node::hasNumberResult):
+        (JSC::DFG::Node::hasDoubleResult):
+        (JSC::DFG::Node::hasJSResult):
+        (JSC::DFG::Node::hasBooleanResult):
+        (JSC::DFG::Node::hasStorageResult):
+        (JSC::DFG::Node::defaultUseKind):
+        (JSC::DFG::Node::defaultEdge):
+        (JSC::DFG::Node::convertToIdentity): Deleted.
+        * dfg/DFGNodeFlags.cpp:
+        (JSC::DFG::dumpNodeFlags):
+        * dfg/DFGNodeFlags.h:
+        (JSC::DFG::canonicalResultRepresentation):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRExitCompiler32_64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGOSRExitCompiler64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGResurrectionForValidationPhase.cpp:
+        (JSC::DFG::ResurrectionForValidationPhase::run):
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::SafeToExecuteEdge::operator()):
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
+        (JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
+        (JSC::DFG::SpeculativeJIT::silentFill):
+        (JSC::DFG::JSValueRegsTemporary::JSValueRegsTemporary):
+        (JSC::DFG::JSValueRegsTemporary::~JSValueRegsTemporary):
+        (JSC::DFG::JSValueRegsTemporary::regs):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
+        (JSC::DFG::SpeculativeJIT::checkGeneratedTypeForToInt32):
+        (JSC::DFG::SpeculativeJIT::compileValueToInt32):
+        (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+        (JSC::DFG::SpeculativeJIT::compileValueRep):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+        (JSC::DFG::SpeculativeJIT::compileAdd):
+        (JSC::DFG::SpeculativeJIT::compileArithSub):
+        (JSC::DFG::SpeculativeJIT::compileArithNegate):
+        (JSC::DFG::SpeculativeJIT::compileArithMul):
+        (JSC::DFG::SpeculativeJIT::compileArithDiv):
+        (JSC::DFG::SpeculativeJIT::compileArithMod):
+        (JSC::DFG::SpeculativeJIT::compare):
+        (JSC::DFG::SpeculativeJIT::compileStrictEq):
+        (JSC::DFG::SpeculativeJIT::speculateNumber):
+        (JSC::DFG::SpeculativeJIT::speculateDoubleReal):
+        (JSC::DFG::SpeculativeJIT::speculate):
+        (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): Deleted.
+        (JSC::DFG::SpeculativeJIT::speculateMachineInt): Deleted.
+        (JSC::DFG::SpeculativeJIT::speculateRealNumber): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::allocate):
+        (JSC::DFG::SpeculativeJIT::use):
+        (JSC::DFG::SpeculativeJIT::boxDouble):
+        (JSC::DFG::SpeculativeJIT::spill):
+        (JSC::DFG::SpeculativeJIT::jsValueResult):
+        (JSC::DFG::SpeculateInt52Operand::SpeculateInt52Operand):
+        (JSC::DFG::SpeculateStrictInt52Operand::SpeculateStrictInt52Operand):
+        (JSC::DFG::SpeculateWhicheverInt52Operand::SpeculateWhicheverInt52Operand):
+        (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillJSValue):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+        (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::convertToDouble): Deleted.
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (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::compileLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::convertToDouble): Deleted.
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * dfg/DFGUseKind.cpp:
+        (WTF::printInternal):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        (JSC::DFG::shouldNotHaveTypeCheck):
+        (JSC::DFG::mayHaveTypeCheck):
+        (JSC::DFG::isNumerical):
+        (JSC::DFG::isDouble):
+        (JSC::DFG::isCell):
+        (JSC::DFG::usesStructure):
+        (JSC::DFG::useKindForResult):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        * dfg/DFGVariadicFunction.h: Removed.
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::createPhiVariables):
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileUpsilon):
+        (JSC::FTL::LowerDFGToLLVM::compilePhi):
+        (JSC::FTL::LowerDFGToLLVM::compileDoubleConstant):
+        (JSC::FTL::LowerDFGToLLVM::compileInt52Constant):
+        (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant):
+        (JSC::FTL::LowerDFGToLLVM::compileDoubleRep):
+        (JSC::FTL::LowerDFGToLLVM::compileValueRep):
+        (JSC::FTL::LowerDFGToLLVM::compileInt52Rep):
+        (JSC::FTL::LowerDFGToLLVM::compileValueToInt32):
+        (JSC::FTL::LowerDFGToLLVM::compileArithAddOrSub):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::LowerDFGToLLVM::compileArithDiv):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMod):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMinOrMax):
+        (JSC::FTL::LowerDFGToLLVM::compileArithAbs):
+        (JSC::FTL::LowerDFGToLLVM::compileArithNegate):
+        (JSC::FTL::LowerDFGToLLVM::compilePutByVal):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareEq):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
+        (JSC::FTL::LowerDFGToLLVM::compare):
+        (JSC::FTL::LowerDFGToLLVM::boolify):
+        (JSC::FTL::LowerDFGToLLVM::lowInt52):
+        (JSC::FTL::LowerDFGToLLVM::lowStrictInt52):
+        (JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52):
+        (JSC::FTL::LowerDFGToLLVM::lowDouble):
+        (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+        (JSC::FTL::LowerDFGToLLVM::strictInt52ToDouble):
+        (JSC::FTL::LowerDFGToLLVM::jsValueToDouble):
+        (JSC::FTL::LowerDFGToLLVM::speculate):
+        (JSC::FTL::LowerDFGToLLVM::speculateNumber):
+        (JSC::FTL::LowerDFGToLLVM::speculateDoubleReal):
+        (JSC::FTL::LowerDFGToLLVM::compileInt52ToValue): Deleted.
+        (JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble): Deleted.
+        (JSC::FTL::LowerDFGToLLVM::setInt52WithStrictValue): Deleted.
+        (JSC::FTL::LowerDFGToLLVM::speculateRealNumber): Deleted.
+        (JSC::FTL::LowerDFGToLLVM::speculateMachineInt): Deleted.
+        * ftl/FTLValueFormat.cpp:
+        (JSC::FTL::reboxAccordingToFormat):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::sanitizeDouble):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::boxDouble):
+
 2014-04-15  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r167199 and r167251.
index 2c3f17c..4ad6a15 100644 (file)
                0FFB921B16D02F010055A5DB /* DFGNodeAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
                5540772018DA58AD00EFF7F2 /* JSArrayBufferView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66BB17B6B5AB00A7AE3F /* JSArrayBufferView.h */; };
                5540772118DA58AD00EFF7F2 /* JSArrayBufferViewInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */; };
                5540772218DA58AD00EFF7F2 /* JSArrayIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */; };
-               5540772518DA58AD00EFF7F2 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };
+               5540772518DA58AD00EFF7F2 /* (null) in Headers */ = {isa = PBXBuildFile; };
                5540772B18DA58AD00EFF7F2 /* JSCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1167D80E19BCC9008066DD /* JSCell.h */; };
                5540772C18DA58AD00EFF7F2 /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; };
                5540772D18DA58AD00EFF7F2 /* JSCInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1DD84918A945BE0026F3FA /* JSCInlines.h */; };
                5540788818DA58AD00EFF7F2 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */; };
                5540788D18DA58AD00EFF7F2 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; };
                5540788F18DA58AD00EFF7F2 /* WriteBarrierInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */; };
-               5540789E18DA58AD00EFF7F2 /* Arguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC257DE50E1F51C50016B6C9 /* Arguments.cpp */; };
-               554078A018DA58AD00EFF7F2 /* ArgumentsIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */; };
                554078AB18DA58AD00EFF7F2 /* ArrayConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */; };
-               554078AD18DA58AD00EFF7F2 /* ArrayIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BDAEC217F4EA1400F6140C /* ArrayIteratorPrototype.cpp */; };
                554078AF18DA58AD00EFF7F2 /* ArrayPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */; };
-               554078B218DA58AD00EFF7F2 /* BooleanConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952320E15EB5600A898AB /* BooleanConstructor.cpp */; };
-               554078B418DA58AD00EFF7F2 /* BooleanPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952340E15EB5600A898AB /* BooleanPrototype.cpp */; };
-               554078D518DA58AD00EFF7F2 /* DateConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD203450E17135E002C7E82 /* DateConstructor.cpp */; };
-               554078D818DA58AD00EFF7F2 /* DatePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD203470E17135E002C7E82 /* DatePrototype.cpp */; };
-               5540794B18DA58AD00EFF7F2 /* ErrorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */; };
-               5540794E18DA58AD00EFF7F2 /* ErrorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */; };
-               5540797D18DA58AD00EFF7F2 /* FunctionConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */; };
-               5540797F18DA58AD00EFF7F2 /* FunctionPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */; };
-               554079C218DA58AD00EFF7F2 /* JSArrayBufferConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66B617B6B5AB00A7AE3F /* JSArrayBufferConstructor.cpp */; };
-               554079C318DA58AD00EFF7F2 /* JSArrayBufferPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66B817B6B5AB00A7AE3F /* JSArrayBufferPrototype.cpp */; };
-               554079C518DA58AD00EFF7F2 /* JSArrayIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */; };
-               554079C718DA58AD00EFF7F2 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };
-               554079D318DA58AD00EFF7F2 /* JSDataViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66BF17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp */; };
-               554079D518DA58AD00EFF7F2 /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; };
-               554079DA18DA58AD00EFF7F2 /* JSGlobalObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */; };
-               554079EB18DA58AD00EFF7F2 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; };
-               554079EE18DA58AD00EFF7F2 /* JSPromiseConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C184E2017BEE240007CB63A /* JSPromiseConstructor.cpp */; };
-               554079F018DA58AD00EFF7F2 /* JSPromiseFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */; };
-               554079F118DA58AD00EFF7F2 /* JSPromisePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C184E1C17BEE22E007CB63A /* JSPromisePrototype.cpp */; };
-               55407A2218DA58AD00EFF7F2 /* ConsolePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53CE08118BC1A5600BEDF76 /* ConsolePrototype.cpp */; };
-               55407A2518DA58AD00EFF7F2 /* MapConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873717CBE85300C3E643 /* MapConstructor.cpp */; };
-               55407A2818DA58AD00EFF7F2 /* MapIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DEF8D182D991400522C22 /* MapIteratorPrototype.cpp */; };
-               55407A2918DA58AD00EFF7F2 /* MapPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873B17CBE8D300C3E643 /* MapPrototype.cpp */; };
-               55407A2E18DA58AD00EFF7F2 /* MathObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A86A0255597D01FF60F7 /* MathObject.cpp */; };
-               55407A3118DA58AD00EFF7F2 /* NameConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2F91560F036008E9222 /* NameConstructor.cpp */; };
-               55407A3318DA58AD00EFF7F2 /* NamePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2FD1560F036008E9222 /* NamePrototype.cpp */; };
                55407A3818DA58AD00EFF7F2 /* NumberConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C20E16D4E900A06E92 /* NumberConstructor.cpp */; };
                55407A3A18DA58AD00EFF7F2 /* NumberPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C40E16D4E900A06E92 /* NumberPrototype.cpp */; };
-               55407A3C18DA58AD00EFF7F2 /* ObjectConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C60E16D4E900A06E92 /* ObjectConstructor.cpp */; };
-               55407A3D18DA58AD00EFF7F2 /* ObjectPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */; };
-               55407A6318DA58AD00EFF7F2 /* RegExpConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */; };
-               55407A6618DA58AD00EFF7F2 /* RegExpPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */; };
-               55407A7B18DA58AD00EFF7F2 /* SetIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A790DD67182F499700588807 /* SetIteratorPrototype.cpp */; };
-               55407A7C18DA58AD00EFF7F2 /* SetPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9F17D12848005F5FF9 /* SetPrototype.cpp */; };
-               55407A8818DA58AD00EFF7F2 /* StringConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C00E16EE3300B34460 /* StringConstructor.cpp */; };
-               55407A8A18DA58AD00EFF7F2 /* StringPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C50E16EE3300B34460 /* StringPrototype.cpp */; };
-               55407AAC18DA58AD00EFF7F2 /* WeakMapConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */; };
-               55407AAE18DA58AD00EFF7F2 /* WeakMapPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA3ADF17DA41AE006538AF /* WeakMapPrototype.cpp */; };
-               55F1380B18EF5F5000982015 /* NativeErrorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */; };
-               55F1380C18EF5FB900982015 /* SetConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299DA317D12858005F5FF9 /* SetConstructor.cpp */; };
                5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; };
                5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
                5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
                0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = "<group>"; };
                0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };
                0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; };
-               0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariadicFunction.h; path = dfg/DFGVariadicFunction.h; sourceTree = "<group>"; };
                0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeUseDef.h; sourceTree = "<group>"; };
                0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLink.cpp; path = ftl/FTLLink.cpp; sourceTree = "<group>"; };
                0F8F2B94172E049E007DBDA5 /* FTLLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLLink.h; path = ftl/FTLLink.h; sourceTree = "<group>"; };
                                0F2BDC411522801700CD8910 /* DFGVariableEvent.h */,
                                0F2BDC421522801700CD8910 /* DFGVariableEventStream.cpp */,
                                0F2BDC431522801700CD8910 /* DFGVariableEventStream.h */,
-                               0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */,
                                0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */,
                                0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */,
                                0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */,
                                5540771818DA58AD00EFF7F2 /* JSActivation.h in Headers */,
                                5540771B18DA58AD00EFF7F2 /* JSArgumentsIterator.h in Headers */,
                                5540772218DA58AD00EFF7F2 /* JSArrayIterator.h in Headers */,
-                               5540772518DA58AD00EFF7F2 /* JSBoundFunction.h in Headers */,
+                               5540772518DA58AD00EFF7F2 /* (null) in Headers */,
                                5540774818DA58AD00EFF7F2 /* JSGlobalObjectDebuggable.h in Headers */,
                                5540774A18DA58AD00EFF7F2 /* JSGlobalObjectFunctions.h in Headers */,
                                5540775918DA58AD00EFF7F2 /* JSMapIterator.h in Headers */,
                                0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */,
                                0F2BDC491522809600CD8910 /* DFGVariableEvent.h in Headers */,
                                0F2BDC4B1522809D00CD8910 /* DFGVariableEventStream.h in Headers */,
-                               0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */,
                                0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */,
                                0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */,
                                0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */,
index 2386762..15642e1 100644 (file)
@@ -157,6 +157,8 @@ public:
     }
     
     // Possibly clobbers src.
+    // FIXME: Don't do that.
+    // https://bugs.webkit.org/show_bug.cgi?id=131690
     void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
     {
         movePackedToInt32(src, dest1);
index 669f029..b7a7c9c 100644 (file)
@@ -37,7 +37,6 @@
 #include "DFGCommon.h"
 #include "DFGDriver.h"
 #include "DFGJITCode.h"
-#include "DFGNode.h"
 #include "DFGWorklist.h"
 #include "Debugger.h"
 #include "Interpreter.h"
index e2014e1..fc72068 100644 (file)
 #include "DFGCommon.h"
 #include "DFGCommonData.h"
 #include "DFGExitProfile.h"
-#include "DFGMinifiedGraph.h"
-#include "DFGOSREntry.h"
-#include "DFGOSRExit.h"
-#include "DFGVariableEventStream.h"
 #include "DeferredCompilationCallback.h"
 #include "EvalCodeCache.h"
 #include "ExecutionCounter.h"
index 60be2dc..8cf920b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -157,9 +157,16 @@ private:
     };
     BooleanResult booleanResult(Node*, AbstractValue&);
     
+    void setBuiltInConstant(Node* node, JSValue value)
+    {
+        AbstractValue& abstractValue = forNode(node);
+        abstractValue.set(m_graph, value);
+        abstractValue.fixTypeForRepresentation(node);
+    }
+    
     void setConstant(Node* node, JSValue value)
     {
-        forNode(node).set(m_graph, value);
+        setBuiltInConstant(node, value);
         m_state.setFoundConstants(true);
     }
     
index 7f480fc..3230a79 100644 (file)
@@ -126,9 +126,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     
     switch (node->op()) {
     case JSConstant:
+    case DoubleConstant:
+    case Int52Constant:
     case WeakJSConstant:
     case PhantomArguments: {
-        forNode(node).set(m_graph, m_graph.valueOfJSConstant(node));
+        setBuiltInConstant(node, m_graph.valueOfJSConstant(node));
         break;
     }
         
@@ -307,39 +309,39 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
     }
         
-    case Int32ToDouble: {
+    case DoubleRep: {
         JSValue child = forNode(node->child1()).value();
         if (child && child.isNumber()) {
-            setConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()));
+            setConstant(node, jsDoubleNumber(child.asNumber()));
             break;
         }
-        if (isInt32Speculation(forNode(node->child1()).m_type))
-            forNode(node).setType(SpecDoubleReal);
-        else
-            forNode(node).setType(SpecDouble);
+        forNode(node).setType(forNode(node->child1()).m_type);
+        forNode(node).fixTypeForRepresentation(node);
         break;
     }
         
-    case Int52ToDouble: {
+    case Int52Rep: {
+        RELEASE_ASSERT(node->child1().useKind() == Int32Use);
+        
         JSValue child = forNode(node->child1()).value();
-        if (child && child.isNumber()) {
+        if (child && child.isInt32()) {
             setConstant(node, child);
             break;
         }
-        forNode(node).setType(SpecDouble);
+        
+        forNode(node).setType(SpecInt32);
         break;
     }
         
-    case Int52ToValue: {
-        JSValue child = forNode(node->child1()).value();
-        if (child && child.isNumber()) {
-            setConstant(node, child);
+    case ValueRep: {
+        JSValue value = forNode(node->child1()).value();
+        if (value) {
+            setConstant(node, value);
             break;
         }
-        SpeculatedType type = forNode(node->child1()).m_type;
-        if (type & SpecInt52)
-            type = (type | SpecInt32 | SpecInt52AsDouble) & ~SpecInt52;
-        forNode(node).setType(type);
+        
+        forNode(node).setType(forNode(node->child1()).m_type);
+        forNode(node).fixTypeForRepresentation(node);
         break;
     }
         
@@ -370,7 +372,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (shouldCheckOverflow(node->arithMode()))
                 node->setCanExit(true);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
                 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt());
                 if (result.isMachineInt()) {
@@ -383,9 +385,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 || !forNode(node->child2()).isType(SpecInt32))
                 node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
-                setConstant(node, jsNumber(left.asNumber() + right.asNumber()));
+                setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
                 break;
             }
             if (isFullRealNumberSpeculation(forNode(node->child1()).m_type)
@@ -426,7 +428,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (shouldCheckOverflow(node->arithMode()))
                 node->setCanExit(true);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
                 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt());
                 if (result.isMachineInt() || !shouldCheckOverflow(node->arithMode())) {
@@ -439,9 +441,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 || !forNode(node->child2()).isType(SpecInt32))
                 node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
-                setConstant(node, jsNumber(left.asNumber() - right.asNumber()));
+                setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -477,7 +479,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (shouldCheckOverflow(node->arithMode()))
                 node->setCanExit(true);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             if (child && child.isMachineInt()) {
                 double doubleResult;
                 if (shouldCheckNegativeZero(node->arithMode()))
@@ -496,9 +498,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (shouldCheckNegativeZero(node->arithMode()))
                 node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (child && child.isNumber()) {
-                setConstant(node, jsNumber(-child.asNumber()));
+                setConstant(node, jsDoubleNumber(-child.asNumber()));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -533,7 +535,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             if (shouldCheckOverflow(node->arithMode()))
                 node->setCanExit(true);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
                 double doubleResult = left.asNumber() * right.asNumber();
                 if (!shouldCheckNegativeZero(node->arithMode()))
@@ -547,9 +549,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt52);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
-                setConstant(node, jsNumber(left.asNumber() * right.asNumber()));
+                setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
                 break;
             }
             if (isFullRealNumberSpeculation(forNode(node->child1()).m_type)
@@ -585,9 +587,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt32);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
-                setConstant(node, jsNumber(left.asNumber() / right.asNumber()));
+                setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -619,9 +621,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt32);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
-                setConstant(node, jsNumber(fmod(left.asNumber(), right.asNumber())));
+                setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -645,11 +647,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt32);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
                 double a = left.asNumber();
                 double b = right.asNumber();
-                setConstant(node, jsNumber(a < b ? a : (b <= a ? b : a + b)));
+                setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -673,11 +675,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt32);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
                 double a = left.asNumber();
                 double b = right.asNumber();
-                setConstant(node, jsNumber(a > b ? a : (b >= a ? b : a + b)));
+                setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -703,9 +705,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             forNode(node).setType(SpecInt32);
             node->setCanExit(true);
             break;
-        case NumberUse:
+        case DoubleRepUse:
             if (child && child.isNumber()) {
-                setConstant(node, jsNumber(child.asNumber()));
+                setConstant(node, jsDoubleNumber(child.asNumber()));
                 break;
             }
             forNode(node).setType(SpecDouble);
@@ -720,7 +722,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ArithSqrt: {
         JSValue child = forNode(node->child1()).value();
         if (child && child.isNumber()) {
-            setConstant(node, jsNumber(sqrt(child.asNumber())));
+            setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
             break;
         }
         forNode(node).setType(SpecDouble);
@@ -730,7 +732,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ArithFRound: {
         JSValue child = forNode(node->child1()).value();
         if (child && child.isNumber()) {
-            setConstant(node, jsNumber(static_cast<float>(child.asNumber())));
+            setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber())));
             break;
         }
         forNode(node).setType(SpecDouble);
@@ -740,7 +742,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ArithSin: {
         JSValue child = forNode(node->child1()).value();
         if (child && child.isNumber()) {
-            setConstant(node, jsNumber(sin(child.asNumber())));
+            setConstant(node, jsDoubleNumber(sin(child.asNumber())));
             break;
         }
         forNode(node).setType(SpecDouble);
@@ -750,7 +752,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ArithCos: {
         JSValue child = forNode(node->child1()).value();
         if (child && child.isNumber()) {
-            setConstant(node, jsNumber(cos(child.asNumber())));
+            setConstant(node, jsDoubleNumber(cos(child.asNumber())));
             break;
         }
         forNode(node).setType(SpecDouble);
@@ -769,7 +771,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             switch (node->child1().useKind()) {
             case BooleanUse:
             case Int32Use:
-            case NumberUse:
+            case DoubleRepUse:
             case UntypedUse:
             case StringUse:
                 break;
index 1d8393a..1a41be5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -67,8 +67,6 @@ void AbstractValue::set(Graph& graph, JSValue value)
     }
     
     m_type = speculationFromValue(value);
-    if (m_type == SpecInt52AsDouble)
-        m_type = SpecInt52;
     m_value = value;
     
     checkConsistency();
@@ -85,6 +83,41 @@ void AbstractValue::set(Graph& graph, Structure* structure)
     checkConsistency();
 }
 
+void AbstractValue::fixTypeForRepresentation(NodeFlags representation)
+{
+    if (representation == NodeResultDouble) {
+        if (m_value) {
+            ASSERT(m_value.isNumber());
+            if (m_value.isInt32())
+                m_value = jsDoubleNumber(m_value.asNumber());
+        }
+        if (m_type & SpecMachineInt) {
+            m_type &= ~SpecMachineInt;
+            m_type |= SpecInt52AsDouble;
+        }
+        RELEASE_ASSERT(!(m_type & ~SpecDouble));
+    } else if (representation == NodeResultInt52) {
+        if (m_type & SpecInt52AsDouble) {
+            m_type &= ~SpecInt52AsDouble;
+            m_type |= SpecInt52;
+        }
+        RELEASE_ASSERT(!(m_type & ~SpecMachineInt));
+    } else {
+        if (m_type & SpecInt52) {
+            m_type &= ~SpecInt52;
+            m_type |= SpecInt52AsDouble;
+        }
+        RELEASE_ASSERT(!(m_type & ~SpecBytecodeTop));
+    }
+    
+    checkConsistency();
+}
+
+void AbstractValue::fixTypeForRepresentation(Node* node)
+{
+    fixTypeForRepresentation(node->result());
+}
+
 FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
 {
     if (isClear())
@@ -244,6 +277,8 @@ void AbstractValue::checkConsistency() const
     
     if (!!m_value) {
         SpeculatedType type = m_type;
+        // This relaxes the assertion below a bit, since we don't know the representation of the
+        // node.
         if (type & SpecInt52)
             type |= SpecInt52AsDouble;
         ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type);
index 4d2938f..b31c8c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,6 +30,7 @@
 
 #include "ArrayProfile.h"
 #include "DFGFiltrationResult.h"
+#include "DFGNodeFlags.h"
 #include "DFGStructureAbstractValue.h"
 #include "JSCell.h"
 #include "SpeculatedType.h"
@@ -39,6 +40,7 @@
 namespace JSC { namespace DFG {
 
 class Graph;
+struct Node;
 
 struct AbstractValue {
     AbstractValue()
@@ -129,6 +131,9 @@ struct AbstractValue {
         checkConsistency();
     }
     
+    void fixTypeForRepresentation(NodeFlags representation);
+    void fixTypeForRepresentation(Node*);
+    
     bool operator==(const AbstractValue& other) const
     {
         return m_type == other.m_type
index 854fdb3..b58e5a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -210,7 +210,6 @@ private:
             break;
         }
             
-        case Identity: 
         case UInt32ToNumber: {
             node->child1()->mergeFlags(flags);
             break;
@@ -378,6 +377,11 @@ private:
             }
             break;
         }
+
+        case Identity: 
+            // This would be trivial to handle but we just assert that we cannot see these yet.
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
             
         // Note: ArithSqrt, ArithSin, and ArithCos and other math intrinsics don't have special
         // rules in here because they are always followed by Phantoms to signify that if the
index aea47db..19d5487 100644 (file)
@@ -33,7 +33,6 @@
 #include "DFGBranchDirection.h"
 #include "DFGFlushedAt.h"
 #include "DFGNode.h"
-#include "DFGVariadicFunction.h"
 #include "Operands.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -98,15 +97,11 @@ struct BasicBlock : RefCounted<BasicBlock> {
     void removePredecessor(BasicBlock* block);
     void replacePredecessor(BasicBlock* from, BasicBlock* to);
 
-#define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost Node* appendNode(Graph&, SpeculatedType valueParamsComma valueParams);
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE)
-#undef DFG_DEFINE_APPEND_NODE
+    template<typename... Params>
+    Node* appendNode(Graph&, SpeculatedType, Params...);
     
-#define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost Node* appendNonTerminal(Graph&, SpeculatedType valueParamsComma valueParams);
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE)
-#undef DFG_DEFINE_APPEND_NODE
+    template<typename... Params>
+    Node* appendNonTerminal(Graph&, SpeculatedType, Params...);
     
     void dump(PrintStream& out) const;
     
index 7f9e38a..4a0fe92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 namespace JSC { namespace DFG {
 
-#define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost inline Node* BasicBlock::appendNode(Graph& graph, SpeculatedType type valueParamsComma valueParams) \
-    { \
-        Node* result = graph.addNode(type valueParamsComma valueArgs); \
-        append(result); \
-        return result; \
-    }
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE)
-#undef DFG_DEFINE_APPEND_NODE
-
-#define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost inline Node* BasicBlock::appendNonTerminal(Graph& graph, SpeculatedType type valueParamsComma valueParams) \
-    { \
-        Node* result = graph.addNode(type valueParamsComma valueArgs); \
-        insertBeforeLast(result); \
-        return result; \
-    }
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE)
-#undef DFG_DEFINE_APPEND_NODE
+template<typename... Params>
+Node* BasicBlock::appendNode(Graph& graph, SpeculatedType type, Params... params)
+{
+    Node* result = graph.addNode(type, params...);
+    append(result);
+    return result;
+}
+
+template<typename... Params>
+Node* BasicBlock::appendNonTerminal(Graph& graph, SpeculatedType type, Params... params)
+{
+    Node* result = graph.addNode(type, params...);
+    insertBeforeLast(result);
+    return result;
+}
 
 } } // namespace JSC::DFG
 
index 0282ad6..25998cd 100644 (file)
@@ -3263,8 +3263,9 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_to_number: {
-            set(VirtualRegister(currentInstruction[1].u.operand),
-                addToGraph(Identity, Edge(get(VirtualRegister(currentInstruction[2].u.operand)), NumberUse)));
+            Node* node = get(VirtualRegister(currentInstruction[2].u.operand));
+            addToGraph(Phantom, Edge(node, NumberUse));
+            set(VirtualRegister(currentInstruction[1].u.operand), node);
             NEXT_OPCODE(op_to_number);
         }
             
index 98e489b..29f811c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -161,29 +161,11 @@ private:
         return 0;
     }
     
-    Node* int32ToDoubleCSE(Node* node)
-    {
-        for (unsigned i = m_indexInBlock; i--;) {
-            Node* otherNode = m_currentBlock->at(i);
-            if (otherNode == node->child1())
-                return 0;
-            switch (otherNode->op()) {
-            case Int32ToDouble:
-                if (otherNode->child1().sanitized() == node->child1().sanitized())
-                    return otherNode;
-                break;
-            default:
-                break;
-            }
-        }
-        return 0;
-    }
-    
     Node* constantCSE(Node* node)
     {
         for (unsigned i = endIndexForPureCSE(); i--;) {
             Node* otherNode = m_currentBlock->at(i);
-            if (otherNode->op() != JSConstant)
+            if (otherNode->op() != node->op())
                 continue;
             
             if (otherNode->constantNumber() != node->constantNumber())
@@ -1148,8 +1130,9 @@ private:
         case CompareEqConstant:
         case ValueToInt32:
         case MakeRope:
-        case Int52ToDouble:
-        case Int52ToValue:
+        case DoubleRep:
+        case ValueRep:
+        case Int52Rep:
             if (cseMode == StoreElimination)
                 break;
             setReplacement(pureCSE(node));
@@ -1177,12 +1160,6 @@ private:
             break;
         }
             
-        case Int32ToDouble:
-            if (cseMode == StoreElimination)
-                break;
-            setReplacement(int32ToDoubleCSE(node));
-            break;
-            
         case GetCallee:
             if (cseMode == StoreElimination)
                 break;
@@ -1261,13 +1238,15 @@ private:
             node->convertToPhantom();
             Node* dataNode = replacement->child1().node();
             ASSERT(dataNode->hasResult());
-            node->child1() = Edge(dataNode);
+            node->child1() = dataNode->defaultEdge();
             m_graph.dethread();
             m_changed = true;
             break;
         }
             
         case JSConstant:
+        case DoubleConstant:
+        case Int52Constant:
             if (cseMode == StoreElimination)
                 break;
             // This is strange, but necessary. Some phases will convert nodes to constants,
index 93e9eb1..0953ab9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,7 +28,6 @@
 
 #include "CodeBlock.h"
 #include "DFGCommon.h"
-#include "DFGNode.h"
 #include "Executable.h"
 #include "Interpreter.h"
 #include "Intrinsic.h"
index d469d24..b54ac41 100644 (file)
@@ -83,6 +83,8 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
     
     switch (node->op()) {
     case JSConstant:
+    case DoubleConstant:
+    case Int52Constant:
     case WeakJSConstant:
     case Identity:
     case Phantom:
@@ -123,15 +125,15 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
     case IsNumber:
     case IsString:
     case LogicalNot:
-    case Int32ToDouble:
     case ExtractOSREntryLocal:
-    case Int52ToDouble:
-    case Int52ToValue:
     case CheckInBounds:
     case ConstantStoragePointer:
     case UInt32ToNumber:
     case DoubleAsInt32:
     case Check:
+    case DoubleRep:
+    case ValueRep:
+    case Int52Rep:
         return;
         
     case MovHint:
index c65720b..c08b3ac 100644 (file)
@@ -299,6 +299,7 @@ private:
             AbstractValue oldValue = m_state.forNode(node);
             AbstractValue constantValue;
             constantValue.set(m_graph, value);
+            constantValue.fixTypeForRepresentation(node);
             if (oldValue.merge(constantValue))
                 continue;
                 
index d3e1f4f..f875b2e 100644 (file)
@@ -194,13 +194,12 @@ private:
                 
             switch (node->op()) {
             case MovHint: {
-                ASSERT(node->child1().useKind() == UntypedUse);
+                ASSERT(node->child1().useKind() == node->child1()->defaultUseKind());
                 if (!node->child1()->shouldGenerate()) {
                     node->setOpAndDefaultFlags(ZombieHint);
                     node->child1() = Edge();
                     break;
                 }
-                node->setOpAndDefaultFlags(MovHint);
                 break;
             }
                 
index 9bfdf5d..4ceda0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -122,7 +122,7 @@ public:
     
     bool willNotHaveCheck() const
     {
-        return isProved() || useKind() == UntypedUse;
+        return isProved() || shouldNotHaveTypeCheck(useKind());
     }
     bool willHaveCheck() const
     {
index 8c2ce67..7ef5e47 100644 (file)
@@ -61,7 +61,7 @@ public:
                 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
             
             for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
-                fixupSetLocalsInBlock(m_graph.block(blockIndex));
+                fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
         }
         
         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
@@ -123,8 +123,10 @@ private:
                 node->convertToIdentity();
             else if (nodeCanSpeculateInt32(node->arithNodeFlags()))
                 node->setArithMode(Arith::CheckOverflow);
-            else
+            else {
                 node->setArithMode(Arith::DoOverflow);
+                node->setResult(NodeResultDouble);
+            }
             break;
         }
             
@@ -135,10 +137,11 @@ private:
                 break;
             }
             if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
-                fixEdge<NumberUse>(node->child1());
-                fixEdge<NumberUse>(node->child2());
+                fixEdge<DoubleRepUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child2());
                 node->setOp(ArithAdd);
                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+                node->setResult(NodeResultDouble);
                 break;
             }
             
@@ -177,8 +180,9 @@ private:
         case ArithSub: {
             if (attemptToMakeIntegerAdd(node))
                 break;
-            fixEdge<NumberUse>(node->child1());
-            fixEdge<NumberUse>(node->child2());
+            fixEdge<DoubleRepUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child2());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -194,14 +198,16 @@ private:
                 break;
             }
             if (m_graph.negateShouldSpeculateMachineInt(node)) {
-                fixEdge<MachineIntUse>(node->child1());
+                fixEdge<Int52RepUse>(node->child1());
                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                     node->setArithMode(Arith::CheckOverflow);
                 else
                     node->setArithMode(Arith::CheckOverflowAndNegativeZero);
+                node->setResult(NodeResultInt52);
                 break;
             }
-            fixEdge<NumberUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child1());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -218,16 +224,18 @@ private:
                 break;
             }
             if (m_graph.mulShouldSpeculateMachineInt(node)) {
-                fixEdge<MachineIntUse>(node->child1());
-                fixEdge<MachineIntUse>(node->child2());
+                fixEdge<Int52RepUse>(node->child1());
+                fixEdge<Int52RepUse>(node->child2());
                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                     node->setArithMode(Arith::CheckOverflow);
                 else
                     node->setArithMode(Arith::CheckOverflowAndNegativeZero);
+                node->setResult(NodeResultInt52);
                 break;
             }
-            fixEdge<NumberUse>(node->child1());
-            fixEdge<NumberUse>(node->child2());
+            fixEdge<DoubleRepUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child2());
+            node->setResult(NodeResultDouble);
             break;
         }
 
@@ -246,24 +254,34 @@ private:
                         node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                     break;
                 }
-                fixEdge<NumberUse>(node->child1());
-                fixEdge<NumberUse>(node->child2());
+                
+                // This will cause conversion nodes to be inserted later.
+                fixEdge<DoubleRepUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child2());
+                
+                // But we have to make sure that everything is phantom'd until after the
+                // DoubleAsInt32 node, which occurs after the Div/Mod node that the conversions
+                // will be insered on.
+                addRequiredPhantom(node->child1().node());
+                addRequiredPhantom(node->child2().node());
 
                 // We don't need to do ref'ing on the children because we're stealing them from
                 // the original division.
                 Node* newDivision = m_insertionSet.insertNode(
                     m_indexInBlock, SpecDouble, *node);
+                newDivision->setResult(NodeResultDouble);
                 
                 node->setOp(DoubleAsInt32);
-                node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
+                node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                     node->setArithMode(Arith::CheckOverflow);
                 else
                     node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                 break;
             }
-            fixEdge<NumberUse>(node->child1());
-            fixEdge<NumberUse>(node->child2());
+            fixEdge<DoubleRepUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child2());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -275,8 +293,9 @@ private:
                 fixEdge<Int32Use>(node->child2());
                 break;
             }
-            fixEdge<NumberUse>(node->child1());
-            fixEdge<NumberUse>(node->child2());
+            fixEdge<DoubleRepUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child2());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -286,7 +305,8 @@ private:
                 fixEdge<Int32Use>(node->child1());
                 break;
             }
-            fixEdge<NumberUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child1());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -294,7 +314,8 @@ private:
         case ArithFRound:
         case ArithSin:
         case ArithCos: {
-            fixEdge<NumberUse>(node->child1());
+            fixEdge<DoubleRepUse>(node->child1());
+            node->setResult(NodeResultDouble);
             break;
         }
             
@@ -306,7 +327,7 @@ private:
             else if (node->child1()->shouldSpeculateInt32())
                 fixEdge<Int32Use>(node->child1());
             else if (node->child1()->shouldSpeculateNumber())
-                fixEdge<NumberUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child1());
             else if (node->child1()->shouldSpeculateString())
                 fixEdge<StringUse>(node->child1());
             break;
@@ -337,14 +358,14 @@ private:
             }
             if (enableInt52()
                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
-                fixEdge<MachineIntUse>(node->child1());
-                fixEdge<MachineIntUse>(node->child2());
+                fixEdge<Int52RepUse>(node->child1());
+                fixEdge<Int52RepUse>(node->child2());
                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
                 break;
             }
             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
-                fixEdge<NumberUse>(node->child1());
-                fixEdge<NumberUse>(node->child2());
+                fixEdge<DoubleRepUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child2());
                 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
                 break;
             }
@@ -402,13 +423,13 @@ private:
             }
             if (enableInt52()
                 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
-                fixEdge<MachineIntUse>(node->child1());
-                fixEdge<MachineIntUse>(node->child2());
+                fixEdge<Int52RepUse>(node->child1());
+                fixEdge<Int52RepUse>(node->child2());
                 break;
             }
             if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
-                fixEdge<NumberUse>(node->child1());
-                fixEdge<NumberUse>(node->child2());
+                fixEdge<DoubleRepUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child2());
                 break;
             }
             if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
@@ -501,7 +522,8 @@ private:
                 break;
             }
             
-            switch (node->arrayMode().type()) {
+            arrayMode = node->arrayMode();
+            switch (arrayMode.type()) {
             case Array::SelectUsingPredictions:
             case Array::Unprofiled:
             case Array::Undecided:
@@ -520,6 +542,30 @@ private:
                 break;
             }
             
+            switch (arrayMode.type()) {
+            case Array::Double:
+                if (!arrayMode.isOutOfBounds())
+                    node->setResult(NodeResultDouble);
+                break;
+                
+            case Array::Float32Array:
+            case Array::Float64Array:
+                node->setResult(NodeResultDouble);
+                break;
+                
+            case Array::Uint32Array:
+                if (node->shouldSpeculateInt32())
+                    break;
+                if (node->shouldSpeculateMachineInt() && enableInt52())
+                    node->setResult(NodeResultInt52);
+                else
+                    node->setResult(NodeResultDouble);
+                break;
+                
+            default:
+                break;
+            }
+            
             break;
         }
 
@@ -559,14 +605,14 @@ private:
                 fixEdge<Int32Use>(child2);
                 fixEdge<Int32Use>(child3);
                 if (child3->prediction() & SpecInt52)
-                    fixEdge<MachineIntUse>(child3);
+                    fixEdge<Int52RepUse>(child3);
                 else
                     fixEdge<Int32Use>(child3);
                 break;
             case Array::Double:
                 fixEdge<KnownCellUse>(child1);
                 fixEdge<Int32Use>(child2);
-                fixEdge<RealNumberUse>(child3);
+                fixEdge<DoubleRepRealUse>(child3);
                 break;
             case Array::Int8Array:
             case Array::Int16Array:
@@ -580,15 +626,15 @@ private:
                 if (child3->shouldSpeculateInt32())
                     fixEdge<Int32Use>(child3);
                 else if (child3->shouldSpeculateMachineInt())
-                    fixEdge<MachineIntUse>(child3);
+                    fixEdge<Int52RepUse>(child3);
                 else
-                    fixEdge<NumberUse>(child3);
+                    fixEdge<DoubleRepUse>(child3);
                 break;
             case Array::Float32Array:
             case Array::Float64Array:
                 fixEdge<KnownCellUse>(child1);
                 fixEdge<Int32Use>(child2);
-                fixEdge<NumberUse>(child3);
+                fixEdge<DoubleRepUse>(child3);
                 break;
             case Array::Contiguous:
             case Array::ArrayStorage:
@@ -630,7 +676,7 @@ private:
                 fixEdge<Int32Use>(node->child2());
                 break;
             case Array::Double:
-                fixEdge<RealNumberUse>(node->child2());
+                fixEdge<DoubleRepRealUse>(node->child2());
                 break;
             case Array::Contiguous:
             case Array::ArrayStorage:
@@ -663,7 +709,7 @@ private:
             else if (node->child1()->shouldSpeculateInt32())
                 fixEdge<Int32Use>(node->child1());
             else if (node->child1()->shouldSpeculateNumber())
-                fixEdge<NumberUse>(node->child1());
+                fixEdge<DoubleRepUse>(node->child1());
 
             Node* logicalNot = node->child1().node();
             if (logicalNot->op() == LogicalNot) {
@@ -760,7 +806,7 @@ private:
                 break;
             case ALL_DOUBLE_INDEXING_TYPES:
                 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
-                    fixEdge<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
+                    fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
                 break;
             case ALL_CONTIGUOUS_INDEXING_TYPES:
             case ALL_ARRAY_STORAGE_INDEXING_TYPES:
@@ -936,7 +982,6 @@ private:
         }
 
         case Phantom:
-        case Identity:
         case Check: {
             switch (node->child1().useKind()) {
             case NumberUse:
@@ -961,16 +1006,19 @@ private:
         case CheckTierUpInLoop:
         case CheckTierUpAtReturn:
         case CheckTierUpAndOSREnter:
-        case Int52ToDouble:
-        case Int52ToValue:
         case InvalidationPoint:
         case CheckArray:
         case CheckInBounds:
         case ConstantStoragePointer:
         case DoubleAsInt32:
-        case Int32ToDouble:
         case ValueToInt32:
         case HardPhantom: // HardPhantom would be trivial to handle but anyway we assert that we won't see it here yet.
+        case DoubleRep:
+        case Int52Rep:
+        case ValueRep:
+        case DoubleConstant:
+        case Int52Constant:
+        case Identity: // This should have been cleaned up.
             // These are just nodes that we don't currently expect to see during fixup.
             // If we ever wanted to insert them prior to fixup, then we just have to create
             // fixup rules for them.
@@ -1312,7 +1360,7 @@ private:
         return true;
     }
     
-    void fixupSetLocalsInBlock(BasicBlock* block)
+    void fixupGetAndSetLocalsInBlock(BasicBlock* block)
     {
         if (!block)
             return;
@@ -1320,28 +1368,49 @@ private:
         m_block = block;
         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
             Node* node = m_currentNode = block->at(m_indexInBlock);
-            if (node->op() != SetLocal)
+            if (node->op() != SetLocal && node->op() != GetLocal)
                 continue;
             
             VariableAccessData* variable = node->variableAccessData();
-            switch (variable->flushFormat()) {
-            case FlushedJSValue:
-                break;
-            case FlushedDouble:
-                fixEdge<NumberUse>(node->child1());
-                break;
-            case FlushedInt32:
-                fixEdge<Int32Use>(node->child1());
-                break;
-            case FlushedInt52:
-                fixEdge<MachineIntUse>(node->child1());
-                break;
-            case FlushedCell:
-                fixEdge<CellUse>(node->child1());
+            switch (node->op()) {
+            case GetLocal:
+                switch (variable->flushFormat()) {
+                case FlushedDouble:
+                    node->setResult(NodeResultDouble);
+                    break;
+                case FlushedInt52:
+                    node->setResult(NodeResultInt52);
+                    break;
+                default:
+                    break;
+                }
                 break;
-            case FlushedBoolean:
-                fixEdge<BooleanUse>(node->child1());
+                
+            case SetLocal:
+                switch (variable->flushFormat()) {
+                case FlushedJSValue:
+                    break;
+                case FlushedDouble:
+                    fixEdge<DoubleRepUse>(node->child1());
+                    break;
+                case FlushedInt32:
+                    fixEdge<Int32Use>(node->child1());
+                    break;
+                case FlushedInt52:
+                    fixEdge<Int52RepUse>(node->child1());
+                    break;
+                case FlushedCell:
+                    fixEdge<CellUse>(node->child1());
+                    break;
+                case FlushedBoolean:
+                    fixEdge<BooleanUse>(node->child1());
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                    break;
+                }
                 break;
+                
             default:
                 RELEASE_ASSERT_NOT_REACHED();
                 break;
@@ -1467,7 +1536,8 @@ private:
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
         case NumberUse:
-        case RealNumberUse:
+        case DoubleRepUse:
+        case DoubleRepRealUse:
             if (variable->doubleFormatState() == UsingDoubleFormat)
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
@@ -1476,7 +1546,7 @@ private:
                 || isBooleanSpeculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             if (isMachineIntSpeculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
@@ -1519,9 +1589,9 @@ private:
         
         UseKind useKind;
         if (node->shouldSpeculateMachineInt())
-            useKind = MachineIntUse;
+            useKind = Int52RepUse;
         else if (node->shouldSpeculateNumber())
-            useKind = NumberUse;
+            useKind = DoubleRepUse;
         else if (node->shouldSpeculateBoolean())
             useKind = BooleanUse;
         else
@@ -1589,9 +1659,10 @@ private:
         }
         
         if (m_graph.addShouldSpeculateMachineInt(node)) {
-            fixEdge<MachineIntUse>(node->child1());
-            fixEdge<MachineIntUse>(node->child2());
+            fixEdge<Int52RepUse>(node->child1());
+            fixEdge<Int52RepUse>(node->child2());
             node->setArithMode(Arith::CheckOverflow);
+            node->setResult(NodeResultInt52);
             return true;
         }
         
@@ -1724,109 +1795,150 @@ private:
         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
             m_currentNode = block->at(m_indexInBlock);
             addPhantomsIfNecessary();
-            if (m_currentNode->containsMovHint())
-                continue;
+            tryToRelaxRepresentation(m_currentNode);
             DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, injectTypeConversionsForEdge);
         }
         clearPhantomsAtEnd();
         m_insertionSet.execute(block);
     }
     
+    void tryToRelaxRepresentation(Node* node)
+    {
+        // Some operations may be able to operate more efficiently over looser representations.
+        // Identify those here. This avoids inserting a redundant representation conversion.
+        // Also, for some operations, like MovHint, this is a necessary optimization: inserting
+        // an otherwise-dead conversion just for a MovHint would break OSR's understanding of
+        // the IR.
+        
+        switch (node->op()) {
+        case MovHint:
+        case Phantom:
+        case Check:
+        case HardPhantom:
+            DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, fixEdgeRepresentation);
+            break;
+            
+        case ValueToInt32:
+            if (node->child1().useKind() == DoubleRepUse
+                && !node->child1()->hasDoubleResult()) {
+                node->child1().setUseKind(NumberUse);
+                break;
+            }
+            break;
+            
+        default:
+            break;
+        }
+    }
+    
+    void fixEdgeRepresentation(Node*, Edge& edge)
+    {
+        switch (edge.useKind()) {
+        case DoubleRepUse:
+        case DoubleRepRealUse:
+            if (edge->hasDoubleResult())
+                break;
+            
+            if (edge->hasInt52Result())
+                edge.setUseKind(Int52RepUse);
+            else if (edge.useKind() == DoubleRepUse)
+                edge.setUseKind(NumberUse);
+            break;
+            
+        case Int52RepUse:
+            // Nothing we can really do.
+            break;
+            
+        case UntypedUse:
+        case NumberUse:
+            if (edge->hasDoubleResult())
+                edge.setUseKind(DoubleRepUse);
+            else if (edge->hasInt52Result())
+                edge.setUseKind(Int52RepUse);
+            break;
+            
+        default:
+            break;
+        }
+    }
+    
     void injectTypeConversionsForEdge(Node* node, Edge& edge)
     {
         ASSERT(node == m_currentNode);
         
-        if (isDouble(edge.useKind())) {
-            if (edge->shouldSpeculateInt32ForArithmetic()) {
-                addRequiredPhantom(edge.node());
-                
-                Node* result = m_insertionSet.insertNode(
-                    m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
-                    node->origin, Edge(edge.node(), NumberUse));
-                
-                edge.setNode(result);
-                return;
-            }
+        switch (edge.useKind()) {
+        case DoubleRepUse:
+        case DoubleRepRealUse: {
+            if (edge->hasDoubleResult())
+                break;
             
-            if (enableInt52() && edge->shouldSpeculateMachineInt()) {
-                // Make all double uses of int52 values have an intermediate Int52ToDouble.
-                // This is for the same reason as Int52ToValue (see below) except that
-                // Int8ToDouble will convert int52's that fit in an int32 into a double
-                // rather than trying to create a boxed int32 like Int52ToValue does.
-                
-                addRequiredPhantom(edge.node());
-                Node* result = m_insertionSet.insertNode(
-                    m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
-                    node->origin, Edge(edge.node(), NumberUse));
-                edge.setNode(result);
-                return;
+            addRequiredPhantom(edge.node());
+
+            Node* result;
+            if (edge->hasInt52Result()) {
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin,
+                    Edge(edge.node(), Int52RepUse));
+            } else {
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecDouble, DoubleRep, node->origin,
+                    Edge(edge.node(), NumberUse));
             }
+
+            edge.setNode(result);
+            break;
         }
-        
-        if (enableInt52() && edge.useKind() != MachineIntUse
-            && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
-            // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
-            // node to ensure that we handle this properly:
-            //
-            // a: SomeInt52
-            // b: ArithAdd(@a, ...)
-            // c: Call(..., @a)
-            // d: ArithAdd(@a, ...)
-            //
-            // Without an intermediate node and just labeling the uses, we will get:
-            //
-            // a: SomeInt52
-            // b: ArithAdd(Int52:@a, ...)
-            // c: Call(..., Untyped:@a)
-            // d: ArithAdd(Int52:@a, ...)
-            //
-            // And now the c->Untyped:@a edge will box the value of @a into a double. This
-            // is bad, because now the d->Int52:@a edge will either have to do double-to-int
-            // conversions, or will have to OSR exit unconditionally. Alternatively we could
-            // have the c->Untyped:@a edge box the value by copying rather than in-place.
-            // But these boxings are also costly so this wouldn't be great.
-            //
-            // The solution we use is to always have non-Int52 uses of predicted Int52's use
-            // an intervening Int52ToValue node:
-            //
-            // a: SomeInt52
-            // b: ArithAdd(Int52:@a, ...)
-            // x: Int52ToValue(Int52:@a)
-            // c: Call(..., Untyped:@x)
-            // d: ArithAdd(Int52:@a, ...)
-            //
-            // Note that even if we had multiple non-int52 uses of @a, the multiple
-            // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
-            // At the same time, @a would continue to be represented as a native int52.
-            //
-            // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
-            // int52's. This would have handled the above example but would fall over for:
-            //
-            // a: SomeInt52
-            // b: Call(..., @a)
-            // c: ArithAdd(@a, ...)
-            //
-            // But the solution we use handles the above gracefully.
+            
+        case Int52RepUse: {
+            if (edge->hasInt52Result())
+                break;
             
             addRequiredPhantom(edge.node());
-            Node* result = m_insertionSet.insertNode(
-                m_indexInBlock, SpecInt52, Int52ToValue,
-                node->origin, Edge(edge.node(), UntypedUse));
+
+            Node* result;
+            if (edge->hasDoubleResult()) {
+                // This will never happen.
+                RELEASE_ASSERT_NOT_REACHED();
+            } else if (edge->shouldSpeculateInt32ForArithmetic()) {
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecInt32, Int52Rep, node->origin,
+                    Edge(edge.node(), Int32Use));
+            } else {
+                // This is only here for dealing with constants.
+                RELEASE_ASSERT(edge->op() == JSConstant);
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecMachineInt, Int52Constant, node->origin,
+                    OpInfo(edge->constantNumber()));
+            }
+
             edge.setNode(result);
-            return;
+            break;
         }
+            
+        default: {
+            if (!edge->hasDoubleResult() && !edge->hasInt52Result())
+                break;
+            
+            addRequiredPhantom(edge.node());
+            
+            Node* result;
+            if (edge->hasDoubleResult()) {
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecDouble, ValueRep, node->origin,
+                    Edge(edge.node(), DoubleRepUse));
+            } else {
+                result = m_insertionSet.insertNode(
+                    m_indexInBlock, SpecInt32 | SpecInt52AsDouble, ValueRep, node->origin,
+                    Edge(edge.node(), Int52RepUse));
+            }
+            
+            edge.setNode(result);
+            break;
+        } }
     }
     
     void addRequiredPhantom(Node* node)
     {
-        if (!m_codeOriginOfPhantoms) {
-            ASSERT(m_requiredPhantoms.isEmpty());
-            m_codeOriginOfPhantoms = m_currentNode->origin.forExit;
-        } else {
-            ASSERT(!m_requiredPhantoms.isEmpty());
-            ASSERT(m_codeOriginOfPhantoms == m_currentNode->origin.forExit);
-        }
-        
         m_requiredPhantoms.append(node);
     }
 
@@ -1835,19 +1947,14 @@ private:
         if (m_requiredPhantoms.isEmpty())
             return;
         
-        RELEASE_ASSERT(!!m_codeOriginOfPhantoms);
-        
-        if (m_currentNode->origin.forExit == m_codeOriginOfPhantoms)
-            return;
-        
         for (unsigned i = m_requiredPhantoms.size(); i--;) {
+            Node* node = m_requiredPhantoms[i];
             m_insertionSet.insertNode(
-                m_indexInBlock, SpecNone, Phantom, NodeOrigin(m_codeOriginOfPhantoms),
-                Edge(m_requiredPhantoms[i], UntypedUse));
+                m_indexInBlock, SpecNone, Phantom, m_currentNode->origin,
+                node->defaultEdge());
         }
         
         m_requiredPhantoms.resize(0);
-        m_codeOriginOfPhantoms = CodeOrigin();
     }
     
     void clearPhantomsAtEnd()
@@ -1863,7 +1970,6 @@ private:
         // https://bugs.webkit.org/show_bug.cgi?id=126778
         
         m_requiredPhantoms.resize(0);
-        m_codeOriginOfPhantoms = CodeOrigin();
     }
     
     BasicBlock* m_block;
@@ -1871,7 +1977,6 @@ private:
     Node* m_currentNode;
     InsertionSet m_insertionSet;
     bool m_profitabilityChanged;
-    CodeOrigin m_codeOriginOfPhantoms;
     Vector<Node*, 3> m_requiredPhantoms;
 };
     
index 6be225f..10e3c00 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,7 @@ inline NodeFlags resultFor(FlushFormat format)
     case FlushedInt52:
         return NodeResultInt52;
     case FlushedDouble:
-        return NodeResultNumber;
+        return NodeResultDouble;
     case FlushedBoolean:
         return NodeResultBoolean;
     }
@@ -83,9 +83,9 @@ inline UseKind useKindFor(FlushFormat format)
     case FlushedInt32:
         return Int32Use;
     case FlushedInt52:
-        return MachineIntUse;
+        return Int52RepUse;
     case FlushedDouble:
-        return NumberUse;
+        return DoubleRepUse;
     case FlushedBoolean:
         return BooleanUse;
     }
index 521e178..3c520b3 100644 (file)
@@ -314,7 +314,7 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
         out.print(comma, inContext(JSValue(node->typedArray()), context));
     if (node->hasStoragePointer())
         out.print(comma, RawPointer(node->storagePointer()));
-    if (op == JSConstant) {
+    if (node->isConstant()) {
         out.print(comma, "$", node->constantNumber());
         JSValue value = valueOfJSConstant(node);
         out.print(" = ", inContext(value, context));
index 8bb674f..16a3c22 100644 (file)
@@ -39,7 +39,6 @@
 #include "DFGNodeAllocator.h"
 #include "DFGPlan.h"
 #include "DFGScannable.h"
-#include "DFGVariadicFunction.h"
 #include "InlineCallFrameSet.h"
 #include "JSStack.h"
 #include "MethodOfGettingAValueProfile.h"
@@ -136,15 +135,13 @@ public:
         ASSERT(!child->misc.replacement);
     }
     
-#define DFG_DEFINE_ADD_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost Node* addNode(SpeculatedType type valueParamsComma valueParams) \
-    { \
-        Node* node = new (m_allocator) Node(valueArgs); \
-        node->predict(type); \
-        return node; \
+    template<typename... Params>
+    Node* addNode(SpeculatedType type, Params... params)
+    {
+        Node* node = new (m_allocator) Node(params...);
+        node->predict(type);
+        return node;
     }
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_ADD_NODE)
-#undef DFG_DEFINE_ADD_NODE
 
     void dethread();
     
index ac94307..b87365f 100644 (file)
@@ -155,14 +155,23 @@ void InPlaceAbstractState::initialize()
             block->valuesAtHead.local(i).clear();
             block->valuesAtTail.local(i).clear();
         }
+        if (m_graph.m_form == SSA)
+            continue;
         if (!block->isOSRTarget)
             continue;
         if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex)
             continue;
         for (size_t i = 0; i < m_graph.m_mustHandleAbstractValues.size(); ++i) {
-            AbstractValue value = m_graph.m_mustHandleAbstractValues[i];
             int operand = m_graph.m_mustHandleAbstractValues.operandForIndex(i);
-            block->valuesAtHead.operand(operand).merge(value);
+            Node* node = block->variablesAtHead.operand(operand);
+            if (!node)
+                continue;
+            AbstractValue value = m_graph.m_mustHandleAbstractValues[i];
+            AbstractValue& abstractValue = block->valuesAtHead.operand(operand);
+            VariableAccessData* variable = node->variableAccessData();
+            FlushFormat format = variable->flushFormat();
+            abstractValue.merge(value);
+            abstractValue.fixTypeForRepresentation(resultFor(format));
         }
         block->cfaShouldRevisit = true;
     }
index 5988152..a44616b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,27 +54,46 @@ public:
     {
         return insert(Insertion(index, element));
     }
-    
-#define DFG_DEFINE_INSERT_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
-    templatePre typeParams templatePost Node* insertNode(size_t index, SpeculatedType type valueParamsComma valueParams) \
-    { \
-        return insert(index, m_graph.addNode(type valueParamsComma valueArgs)); \
+
+    template<typename... Params>
+    Node* insertNode(size_t index, SpeculatedType type, Params... params)
+    {
+        return insert(index, m_graph.addNode(type, params...));
     }
-    DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_INSERT_NODE)
-#undef DFG_DEFINE_INSERT_NODE
     
-    Node* insertConstant(size_t index, NodeOrigin origin, JSValue value)
+    Node* insertConstant(
+        size_t index, NodeOrigin origin, JSValue value,
+        NodeType op = JSConstant)
     {
         unsigned constantReg =
             m_graph.constantRegisterForConstant(value);
         return insertNode(
-            index, speculationFromValue(value), JSConstant, origin,
-            OpInfo(constantReg));
+            index, speculationFromValue(value), op, origin, OpInfo(constantReg));
+    }
+    
+    Node* insertConstant(
+        size_t index, CodeOrigin origin, JSValue value, NodeType op = JSConstant)
+    {
+        return insertConstant(index, NodeOrigin(origin), value, op);
+    }
+    
+    Edge insertConstantForUse(
+        size_t index, NodeOrigin origin, JSValue value, UseKind useKind)
+    {
+        NodeType op;
+        if (isDouble(useKind))
+            op = DoubleConstant;
+        else if (useKind == Int52RepUse)
+            op = Int52Constant;
+        else
+            op = JSConstant;
+        return Edge(insertConstant(index, origin, value, op), useKind);
     }
     
-    Node* insertConstant(size_t index, CodeOrigin origin, JSValue value)
+    Edge insertConstantForUse(
+        size_t index, CodeOrigin origin, JSValue value, UseKind useKind)
     {
-        return insertConstant(index, NodeOrigin(origin), value);
+        return insertConstantForUse(index, NodeOrigin(origin), value, useKind);
     }
 
     void execute(BasicBlock* block)
index e5f396b..96fdc68 100644 (file)
@@ -370,10 +370,10 @@ private:
         if (!addend)
             return source.node();
         return m_insertionSet.insertNode(
-            nodeIndex, source->prediction(), ArithAdd, origin, OpInfo(arithMode),
-            source, Edge(
-                m_insertionSet.insertConstant(nodeIndex, origin, jsNumber(addend)),
-                source.useKind()));
+            nodeIndex, source->prediction(), source->result(),
+            ArithAdd, origin, OpInfo(arithMode), source,
+            m_insertionSet.insertConstantForUse(
+                nodeIndex, origin, jsNumber(addend), source.useKind()));
     }
     
     Node* insertMustAdd(
@@ -381,7 +381,7 @@ private:
     {
         Node* result = insertAdd(nodeIndex, origin, source, addend);
         m_insertionSet.insertNode(
-            nodeIndex, SpecNone, HardPhantom, origin, Edge(result, UntypedUse));
+            nodeIndex, SpecNone, HardPhantom, origin, result->defaultEdge());
         return result;
     }
     
index 8a8e692..933664a 100644 (file)
@@ -91,6 +91,15 @@ bool Node::hasVariableAccessData(Graph& graph)
     }
 }
 
+void Node::convertToIdentity()
+{
+    RELEASE_ASSERT(child1());
+    RELEASE_ASSERT(!child2());
+    NodeFlags result = canonicalResultRepresentation(this->result());
+    setOpAndDefaultFlags(Identity);
+    setResult(result);
+}
+
 } } // namespace JSC::DFG
 
 namespace WTF {
@@ -121,7 +130,10 @@ void printInternal(PrintStream& out, Node* node)
         return;
     }
     out.print("@", node->index());
-    out.print(AbbreviatedSpeculationDump(node->prediction()));
+    if (node->hasDoubleResult())
+        out.print("<Double>");
+    else if (node->hasInt52Result())
+        out.print("<Int52>");
 }
 
 } // namespace WTF
index ed126b9..25cef02 100644 (file)
@@ -38,6 +38,7 @@
 #include "DFGNodeFlags.h"
 #include "DFGNodeOrigin.h"
 #include "DFGNodeType.h"
+#include "DFGUseKind.h"
 #include "DFGVariableAccessData.h"
 #include "GetByIdVariant.h"
 #include "JSCJSValue.h"
@@ -239,6 +240,22 @@ struct Node {
         ASSERT(!(m_flags & NodeHasVarArgs));
     }
 
+    // Construct a node with up to 3 children, no immediate value.
+    Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
+        : origin(nodeOrigin)
+        , children(AdjacencyList::Fixed, child1, child2, child3)
+        , m_virtualRegister(VirtualRegister())
+        , m_refCount(1)
+        , m_prediction(SpecNone)
+        , m_opInfo(0)
+        , m_opInfo2(0)
+    {
+        misc.replacement = 0;
+        setOpAndDefaultFlags(op);
+        setResult(result);
+        ASSERT(!(m_flags & NodeHasVarArgs));
+    }
+
     // Construct a node with up to 3 children and an immediate value.
     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
         : origin(nodeOrigin)
@@ -254,6 +271,22 @@ struct Node {
         ASSERT(!(m_flags & NodeHasVarArgs));
     }
 
+    // Construct a node with up to 3 children and an immediate value.
+    Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
+        : origin(nodeOrigin)
+        , children(AdjacencyList::Fixed, child1, child2, child3)
+        , m_virtualRegister(VirtualRegister())
+        , m_refCount(1)
+        , m_prediction(SpecNone)
+        , m_opInfo(imm.m_value)
+        , m_opInfo2(0)
+    {
+        misc.replacement = 0;
+        setOpAndDefaultFlags(op);
+        setResult(result);
+        ASSERT(!(m_flags & NodeHasVarArgs));
+    }
+
     // Construct a node with up to 3 children and two immediate values.
     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
         : origin(nodeOrigin)
@@ -325,6 +358,18 @@ struct Node {
         return filterFlags(~flags);
     }
     
+    void setResult(NodeFlags result)
+    {
+        ASSERT(!(result & ~NodeResultMask));
+        clearFlags(NodeResultMask);
+        mergeFlags(result);
+    }
+    
+    NodeFlags result() const
+    {
+        return flags() & NodeResultMask;
+    }
+    
     void setOpAndDefaultFlags(NodeType op)
     {
         m_op = op;
@@ -341,12 +386,7 @@ struct Node {
         setOpAndDefaultFlags(Phantom);
     }
 
-    void convertToIdentity()
-    {
-        RELEASE_ASSERT(child1());
-        RELEASE_ASSERT(!child2());
-        setOpAndDefaultFlags(Identity);
-    }
+    void convertToIdentity();
 
     bool mustGenerate()
     {
@@ -368,7 +408,14 @@ struct Node {
     
     bool isConstant()
     {
-        return op() == JSConstant;
+        switch (op()) {
+        case JSConstant:
+        case DoubleConstant:
+        case Int52Constant:
+            return true;
+        default:
+            return false;
+        }
     }
     
     bool isWeakConstant()
@@ -385,6 +432,8 @@ struct Node {
     {
         switch (op()) {
         case JSConstant:
+        case DoubleConstant:
+        case Int52Constant:
         case WeakJSConstant:
         case PhantomArguments:
             return true;
@@ -401,7 +450,12 @@ struct Node {
     
     void convertToConstant(unsigned constantNumber)
     {
-        m_op = JSConstant;
+        if (hasDoubleResult())
+            m_op = DoubleConstant;
+        else if (hasInt52Result())
+            m_op = Int52Constant;
+        else
+            m_op = JSConstant;
         m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
         m_opInfo = constantNumber;
         children.reset();
@@ -502,6 +556,8 @@ struct Node {
         case WeakJSConstant:
             return JSValue(weakConstant());
         case JSConstant:
+        case DoubleConstant:
+        case Int52Constant:
             return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
         case PhantomArguments:
             return JSValue();
@@ -797,32 +853,52 @@ struct Node {
     
     bool hasResult()
     {
-        return m_flags & NodeResultMask;
+        return !!result();
     }
 
     bool hasInt32Result()
     {
-        return (m_flags & NodeResultMask) == NodeResultInt32;
+        return result() == NodeResultInt32;
+    }
+    
+    bool hasInt52Result()
+    {
+        return result() == NodeResultInt52;
     }
     
     bool hasNumberResult()
     {
-        return (m_flags & NodeResultMask) == NodeResultNumber;
+        return result() == NodeResultNumber;
+    }
+    
+    bool hasDoubleResult()
+    {
+        return result() == NodeResultDouble;
     }
     
     bool hasJSResult()
     {
-        return (m_flags & NodeResultMask) == NodeResultJS;
+        return result() == NodeResultJS;
     }
     
     bool hasBooleanResult()
     {
-        return (m_flags & NodeResultMask) == NodeResultBoolean;
+        return result() == NodeResultBoolean;
     }
 
     bool hasStorageResult()
     {
-        return (m_flags & NodeResultMask) == NodeResultStorage;
+        return result() == NodeResultStorage;
+    }
+    
+    UseKind defaultUseKind()
+    {
+        return useKindForResult(result());
+    }
+    
+    Edge defaultEdge()
+    {
+        return Edge(this, defaultUseKind());
     }
 
     bool isJump()
index 83287f9..ecfad2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,6 +47,9 @@ void dumpNodeFlags(PrintStream& actualOut, NodeFlags flags)
         case NodeResultNumber:
             out.print(comma, "Number");
             break;
+        case NodeResultDouble:
+            out.print(comma, "Double");
+            break;
         case NodeResultInt32:
             out.print(comma, "Int32");
             break;
index b3cb112..0babd94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,10 +38,11 @@ namespace JSC { namespace DFG {
 #define NodeResultMask                   0x0007
 #define NodeResultJS                     0x0001
 #define NodeResultNumber                 0x0002
-#define NodeResultInt32                  0x0003
-#define NodeResultInt52                  0x0004
-#define NodeResultBoolean                0x0005
-#define NodeResultStorage                0x0006
+#define NodeResultDouble                 0x0003
+#define NodeResultInt32                  0x0004
+#define NodeResultInt52                  0x0005
+#define NodeResultBoolean                0x0006
+#define NodeResultStorage                0x0007
                                 
 #define NodeMustGenerate                 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
 #define NodeHasVarArgs                   0x0010
@@ -114,6 +115,20 @@ static inline bool nodeCanSpeculateInt52(NodeFlags flags)
     return true;
 }
 
+// FIXME: Get rid of this.
+// https://bugs.webkit.org/show_bug.cgi?id=131689
+static inline NodeFlags canonicalResultRepresentation(NodeFlags flags)
+{
+    switch (flags) {
+    case NodeResultDouble:
+    case NodeResultInt52:
+    case NodeResultStorage:
+        return flags;
+    default:
+        return NodeResultJS;
+    }
+}
+
 void dumpNodeFlags(PrintStream&, NodeFlags);
 MAKE_PRINT_ADAPTOR(NodeFlagsDump, NodeFlags, dumpNodeFlags);
 
index 7d0a3b5..2c31fb2 100644 (file)
@@ -37,6 +37,10 @@ namespace JSC { namespace DFG {
     /* A constant in the CodeBlock's constant pool. */\
     macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
     \
+    /* Constants with specific representations. */\
+    macro(DoubleConstant, NodeResultDouble | NodeDoesNotExit) \
+    macro(Int52Constant, NodeResultInt52 | NodeDoesNotExit) \
+    \
     /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
     /* code block. */\
     macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
@@ -106,15 +110,13 @@ namespace JSC { namespace DFG {
     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
     macro(UInt32ToNumber, NodeResultNumber) \
     \
-    /* Used to cast known integers to doubles, so as to separate the double form */\
-    /* of the value from the integer form. */\
-    macro(Int32ToDouble, NodeResultNumber) \
-    /* Used to speculate that a double value is actually an integer. */\
+    /* Attempt to truncate a double to int32; this will exit if it can't do it. */\
     macro(DoubleAsInt32, NodeResultInt32) \
-    /* Used to separate representation and register allocation of Int52's represented */\
-    /* as values. */\
-    macro(Int52ToValue, NodeResultJS) \
-    macro(Int52ToDouble, NodeResultNumber) \
+    \
+    /* Change the representation of a value. */\
+    macro(DoubleRep, NodeResultDouble) \
+    macro(Int52Rep, NodeResultInt52) \
+    macro(ValueRep, NodeResultJS) \
     \
     /* Nodes for arithmetic operations. */\
     macro(ArithAdd, NodeResultNumber) \
index 63b0bcc..60b2858 100644 (file)
@@ -269,9 +269,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
         
         switch (recovery.technique()) {
         case InPair:
-        case InFPR:
         case DisplacedInJSStack:
-        case DoubleDisplacedInJSStack:
             m_jit.load32(
                 &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag,
                 GPRInfo::regT0);
@@ -286,6 +284,14 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
                 AssemblyHelpers::payloadFor(operand));
             break;
             
+        case InFPR:
+        case DoubleDisplacedInJSStack:
+            m_jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
+            m_jit.loadDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
+            m_jit.sanitizeDouble(FPRInfo::fpRegT0);
+            m_jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor(operand));
+            break;
+
         case UnboxedInt32InGPR:
         case Int32DisplacedInJSStack:
             m_jit.load32(
index 4b2687d..fd70159 100644 (file)
@@ -297,6 +297,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
         case DoubleDisplacedInJSStack:
             m_jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
             m_jit.loadDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
+            m_jit.sanitizeDouble(FPRInfo::fpRegT0);
             m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
             m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
             break;
index 2308c34..87db750 100644 (file)
@@ -490,7 +490,6 @@ private:
         case PutByValAlias:
         case GetArrayLength:
         case GetTypedArrayByteOffset:
-        case Int32ToDouble:
         case DoubleAsInt32:
         case GetLocalUnlinked:
         case GetMyArgumentsLength:
@@ -504,11 +503,15 @@ private:
         case CheckTierUpAtReturn:
         case CheckTierUpAndOSREnter:
         case InvalidationPoint:
-        case Int52ToValue:
-        case Int52ToDouble:
         case CheckInBounds:
         case ValueToInt32:
-        case HardPhantom: {
+        case HardPhantom:
+        case DoubleRep:
+        case Int52Rep:
+        case ValueRep:
+        case DoubleConstant:
+        case Int52Constant:
+        case Identity: {
             // This node should never be visible at this stage of compilation. It is
             // inserted by fixup(), which follows this phase.
             RELEASE_ASSERT_NOT_REACHED();
@@ -535,10 +538,6 @@ private:
             changed |= setPrediction(SpecBoolean);
             break;
 
-        case Identity:
-            changed |= mergePrediction(node->child1()->prediction());
-            break;
-
 #ifndef NDEBUG
         // These get ignored because they don't return anything.
         case StoreBarrier:
index 9324a4b..710ad0f 100644 (file)
@@ -57,7 +57,7 @@ public:
                 if (!node->hasResult())
                     continue;
                 insertionSet.insertNode(
-                    nodeIndex + 1, SpecNone, Phantom, node->origin, Edge(node));
+                    nodeIndex + 1, SpecNone, Phantom, node->origin, node->defaultEdge());
             }
             
             insertionSet.execute(block);
index 12d31f2..9e31b67 100644 (file)
@@ -192,7 +192,7 @@ public:
                         } else {
                             m_insertionSet.insertNode(
                                 0, SpecNone, MovHint, NodeOrigin(),
-                                OpInfo(variable->local().offset()), Edge(node));
+                                OpInfo(variable->local().offset()), node->defaultEdge());
                         }
                     }
                 }
@@ -350,7 +350,9 @@ public:
                     VariableAccessData* variable = node->variableAccessData();
                     if (variable->isCaptured())
                         break;
-                    node->child1().setNode(block->variablesAtHead.operand(variable->local()));
+                    ASSERT(node->child1().useKind() == UntypedUse);
+                    node->child1() =
+                        block->variablesAtHead.operand(variable->local())->defaultEdge();
                     node->convertToPhantom();
                     // This is only for Upsilons. An Upsilon will only refer to a
                     // PhantomLocal if there were no SetLocals or GetLocals in the block.
@@ -363,7 +365,7 @@ public:
                     if (variable->isCaptured())
                         break;
                     node->setOpAndDefaultFlags(GetArgument);
-                    node->mergeFlags(resultFor(node->variableAccessData()->flushFormat()));
+                    node->setResult(resultFor(node->variableAccessData()->flushFormat()));
                     break;
                 }
 
index 521a32c..f235cd8 100644 (file)
@@ -46,7 +46,9 @@ public:
         switch (edge.useKind()) {
         case UntypedUse:
         case Int32Use:
-        case RealNumberUse:
+        case DoubleRepUse:
+        case DoubleRepRealUse:
+        case Int52RepUse:
         case NumberUse:
         case BooleanUse:
         case CellUse:
@@ -61,7 +63,6 @@ public:
         case NotCellUse:
         case OtherUse:
         case MiscUse:
-        case MachineIntUse:
             return;
             
         case KnownInt32Use:
@@ -69,11 +70,6 @@ public:
                 m_result = false;
             return;
             
-        case KnownNumberUse:
-            if (m_state.forNode(edge).m_type & ~SpecFullNumber)
-                m_result = false;
-            return;
-            
         case KnownCellUse:
             if (m_state.forNode(edge).m_type & ~SpecCell)
                 m_result = false;
@@ -111,6 +107,8 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
 
     switch (node->op()) {
     case JSConstant:
+    case DoubleConstant:
+    case Int52Constant:
     case WeakJSConstant:
     case Identity:
     case ToThis:
@@ -137,7 +135,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case BitURShift:
     case ValueToInt32:
     case UInt32ToNumber:
-    case Int32ToDouble:
     case DoubleAsInt32:
     case ArithAdd:
     case ArithSub:
@@ -242,8 +239,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
     case LoopHint:
-    case Int52ToDouble:
-    case Int52ToValue:
     case StoreBarrier:
     case StoreBarrierWithNullCheck:
     case InvalidationPoint:
@@ -255,6 +250,9 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case Check:
     case MultiGetByOffset:
     case MultiPutByOffset:
+    case ValueRep:
+    case DoubleRep:
+    case Int52Rep:
         return true;
         
     case GetByVal:
index d2a8b40..f384d77 100644 (file)
@@ -332,8 +332,6 @@ SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spil
     } else if (registerFormat == DataFormatInt52) {
         if (node->hasConstant())
             fillAction = SetInt52Constant;
-        else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)
-            fillAction = Load32PayloadConvertToInt52;
         else if (info.spillFormat() == DataFormatInt52)
             fillAction = Load64;
         else if (info.spillFormat() == DataFormatStrictInt52)
@@ -341,17 +339,12 @@ SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spil
         else if (info.spillFormat() == DataFormatNone)
             fillAction = Load64;
         else {
-            // Should never happen. Anything that qualifies as an int32 will never
-            // be turned into a cell (immediate spec fail) or a double (to-double
-            // conversions involve a separate node).
             RELEASE_ASSERT_NOT_REACHED();
             fillAction = Load64; // Make GCC happy.
         }
     } else if (registerFormat == DataFormatStrictInt52) {
         if (node->hasConstant())
             fillAction = SetStrictInt52Constant;
-        else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)
-            fillAction = Load32PayloadSignExtend;
         else if (info.spillFormat() == DataFormatInt52)
             fillAction = Load64ShiftInt52Right;
         else if (info.spillFormat() == DataFormatStrictInt52)
@@ -359,9 +352,6 @@ SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spil
         else if (info.spillFormat() == DataFormatNone)
             fillAction = Load64;
         else {
-            // Should never happen. Anything that qualifies as an int32 will never
-            // be turned into a cell (immediate spec fail) or a double (to-double
-            // conversions involve a separate node).
             RELEASE_ASSERT_NOT_REACHED();
             fillAction = Load64; // Make GCC happy.
         }
@@ -376,9 +366,6 @@ SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spil
         } else if (info.spillFormat() == DataFormatInt32) {
             ASSERT(registerFormat == DataFormatJSInt32);
             fillAction = Load32PayloadBoxInt;
-        } else if (info.spillFormat() == DataFormatDouble) {
-            ASSERT(registerFormat == DataFormatJSDouble);
-            fillAction = LoadDoubleBoxDouble;
         } else
             fillAction = Load64;
 #else
@@ -434,14 +421,12 @@ SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForFPR(VirtualRegister spil
     if (node->hasConstant()) {
         ASSERT(isNumberConstant(node));
         fillAction = SetDoubleConstant;
-    } else if (info.spillFormat() != DataFormatNone && info.spillFormat() != DataFormatDouble) {
-        // it was already spilled previously and not as a double, which means we need unboxing.
-        ASSERT(info.spillFormat() & DataFormatJS);
-        fillAction = LoadJSUnboxDouble;
-    } else
+    } else {
+        ASSERT(info.spillFormat() == DataFormatNone || info.spillFormat() == DataFormatDouble);
         fillAction = LoadDouble;
+    }
 #elif USE(JSVALUE32_64)
-    ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);
+    ASSERT(info.registerFormat() == DataFormatDouble);
     if (node->hasConstant()) {
         ASSERT(isNumberConstant(node));
         fillAction = SetDoubleConstant;
@@ -528,14 +513,6 @@ void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan, GPRReg canTr
         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
         m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
         break;
-    case LoadDoubleBoxDouble:
-        m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
-        m_jit.sub64(GPRInfo::tagTypeNumberRegister, plan.gpr());
-        break;
-    case LoadJSUnboxDouble:
-        m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), canTrample);
-        unboxDouble(canTrample, plan.fpr());
-        break;
 #else
     case SetJSConstantTag:
         m_jit.move(Imm32(valueOfJSConstant(plan.node()).tag()), plan.gpr());
@@ -1039,6 +1016,29 @@ GPRTemporary::GPRTemporary(
 }
 #endif // USE(JSVALUE32_64)
 
+JSValueRegsTemporary::JSValueRegsTemporary() { }
+
+JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit)
+#if USE(JSVALUE64)
+    : m_gpr(jit)
+#else
+    : m_payloadGPR(jit)
+    , m_tagGPR(jit)
+#endif
+{
+}
+
+JSValueRegsTemporary::~JSValueRegsTemporary() { }
+
+JSValueRegs JSValueRegsTemporary::regs()
+{
+#if USE(JSVALUE64)
+    return JSValueRegs(m_gpr.gpr());
+#else
+    return JSValueRegs(m_tagGPR.gpr(), m_payloadGPR.gpr());
+#endif
+}
+
 void GPRTemporary::adopt(GPRTemporary& other)
 {
     ASSERT(!m_jit);
@@ -1258,10 +1258,10 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node* node, MacroAssembler::Relationa
         if (node->isBinaryUseKind(Int32Use))
             compilePeepHoleInt32Branch(node, branchNode, condition);
 #if USE(JSVALUE64)
-        else if (node->isBinaryUseKind(MachineIntUse))
+        else if (node->isBinaryUseKind(Int52RepUse))
             compilePeepHoleInt52Branch(node, branchNode, condition);
 #endif // USE(JSVALUE64)
-        else if (node->isBinaryUseKind(NumberUse))
+        else if (node->isBinaryUseKind(DoubleRepUse))
             compilePeepHoleDoubleBranch(node, branchNode, doubleCondition);
         else if (node->op() == CompareEq) {
             if (node->isBinaryUseKind(StringUse) || node->isBinaryUseKind(StringIdentUse)) {
@@ -1817,16 +1817,13 @@ GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)
     case DataFormatJSCell:
     case DataFormatJS:
     case DataFormatJSBoolean:
+    case DataFormatJSDouble:
         return GeneratedOperandJSValue;
 
     case DataFormatJSInt32:
     case DataFormatInt32:
         return GeneratedOperandInteger;
 
-    case DataFormatJSDouble:
-    case DataFormatDouble:
-        return GeneratedOperandDouble;
-        
     default:
         RELEASE_ASSERT_NOT_REACHED();
         return GeneratedOperandTypeUnknown;
@@ -1845,7 +1842,7 @@ void SpeculativeJIT::compileValueToInt32(Node* node)
     }
         
 #if USE(JSVALUE64)
-    case MachineIntUse: {
+    case Int52RepUse: {
         SpeculateStrictInt52Operand op1(this, node->child1());
         GPRTemporary result(this, Reuse, op1);
         GPRReg op1GPR = op1.gpr();
@@ -1855,6 +1852,19 @@ void SpeculativeJIT::compileValueToInt32(Node* node)
         return;
     }
 #endif // USE(JSVALUE64)
+        
+    case DoubleRepUse: {
+        GPRTemporary result(this);
+        SpeculateDoubleOperand op1(this, node->child1());
+        FPRReg fpr = op1.fpr();
+        GPRReg gpr = result.gpr();
+        JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
+        
+        addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
+        
+        int32Result(gpr, node);
+        return;
+    }
     
     case NumberUse:
     case NotCellUse: {
@@ -1866,18 +1876,6 @@ void SpeculativeJIT::compileValueToInt32(Node* node)
             int32Result(result.gpr(), node, op1.format());
             return;
         }
-        case GeneratedOperandDouble: {
-            GPRTemporary result(this);
-            SpeculateDoubleOperand op1(this, node->child1(), ManualOperandSpeculation);
-            FPRReg fpr = op1.fpr();
-            GPRReg gpr = result.gpr();
-            JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
-            
-            addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
-
-            int32Result(gpr, node);
-            return;
-        }
         case GeneratedOperandJSValue: {
             GPRTemporary result(this);
 #if USE(JSVALUE64)
@@ -2066,70 +2064,139 @@ void SpeculativeJIT::compileDoubleAsInt32(Node* node)
     int32Result(resultGPR, node);
 }
 
-void SpeculativeJIT::compileInt32ToDouble(Node* node)
+void SpeculativeJIT::compileDoubleRep(Node* node)
 {
-    ASSERT(!isInt32Constant(node->child1().node())); // This should have been constant folded.
+    switch (node->child1().useKind()) {
+    case NumberUse: {
+        ASSERT(!isNumberConstant(node->child1().node())); // This should have been constant folded.
     
-    if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) {
-        SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
-        FPRTemporary result(this);
-        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
-        doubleResult(result.fpr(), node);
-        return;
-    }
+        if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) {
+            SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
+            FPRTemporary result(this);
+            m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+            doubleResult(result.fpr(), node);
+            return;
+        }
     
-    JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
-    FPRTemporary result(this);
+        JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
+        FPRTemporary result(this);
     
 #if USE(JSVALUE64)
-    GPRTemporary temp(this);
+        GPRTemporary temp(this);
 
-    GPRReg op1GPR = op1.gpr();
-    GPRReg tempGPR = temp.gpr();
-    FPRReg resultFPR = result.fpr();
+        GPRReg op1GPR = op1.gpr();
+        GPRReg tempGPR = temp.gpr();
+        FPRReg resultFPR = result.fpr();
     
-    JITCompiler::Jump isInteger = m_jit.branch64(
-        MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
+        JITCompiler::Jump isInteger = m_jit.branch64(
+            MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
     
-    if (needsTypeCheck(node->child1(), SpecFullNumber)) {
-        typeCheck(
-            JSValueRegs(op1GPR), node->child1(), SpecFullNumber,
-            m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
-    }
+        if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
+            typeCheck(
+                JSValueRegs(op1GPR), node->child1(), SpecBytecodeNumber,
+                m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+        }
     
-    m_jit.move(op1GPR, tempGPR);
-    unboxDouble(tempGPR, resultFPR);
-    JITCompiler::Jump done = m_jit.jump();
+        m_jit.move(op1GPR, tempGPR);
+        unboxDouble(tempGPR, resultFPR);
+        JITCompiler::Jump done = m_jit.jump();
     
-    isInteger.link(&m_jit);
-    m_jit.convertInt32ToDouble(op1GPR, resultFPR);
-    done.link(&m_jit);
-#else
-    FPRTemporary temp(this);
+        isInteger.link(&m_jit);
+        m_jit.convertInt32ToDouble(op1GPR, resultFPR);
+        done.link(&m_jit);
+#else // USE(JSVALUE64) -> this is the 32_64 case
+        FPRTemporary temp(this);
     
-    GPRReg op1TagGPR = op1.tagGPR();
-    GPRReg op1PayloadGPR = op1.payloadGPR();
-    FPRReg tempFPR = temp.fpr();
-    FPRReg resultFPR = result.fpr();
+        GPRReg op1TagGPR = op1.tagGPR();
+        GPRReg op1PayloadGPR = op1.payloadGPR();
+        FPRReg tempFPR = temp.fpr();
+        FPRReg resultFPR = result.fpr();
     
-    JITCompiler::Jump isInteger = m_jit.branch32(
-        MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
+        JITCompiler::Jump isInteger = m_jit.branch32(
+            MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
     
-    if (needsTypeCheck(node->child1(), SpecFullNumber)) {
-        typeCheck(
-            JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber,
-            m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
-    }
+        if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
+            typeCheck(
+                JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecBytecodeNumber,
+                m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+        }
     
-    unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
-    JITCompiler::Jump done = m_jit.jump();
+        unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
+        JITCompiler::Jump done = m_jit.jump();
     
-    isInteger.link(&m_jit);
-    m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
-    done.link(&m_jit);
-#endif
+        isInteger.link(&m_jit);
+        m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
+        done.link(&m_jit);
+#endif // USE(JSVALUE64)
     
-    doubleResult(resultFPR, node);
+        doubleResult(resultFPR, node);
+        return;
+    }
+        
+#if USE(JSVALUE64)
+    case Int52RepUse: {
+        SpeculateStrictInt52Operand value(this, node->child1());
+        FPRTemporary result(this);
+        
+        GPRReg valueGPR = value.gpr();
+        FPRReg resultFPR = result.fpr();
+
+        m_jit.convertInt64ToDouble(valueGPR, resultFPR);
+        
+        doubleResult(resultFPR, node);
+        return;
+    }
+#endif // USE(JSVALUE64)
+        
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
+}
+
+void SpeculativeJIT::compileValueRep(Node* node)
+{
+    switch (node->child1().useKind()) {
+    case DoubleRepUse: {
+        SpeculateDoubleOperand value(this, node->child1());
+        JSValueRegsTemporary result(this);
+        
+        FPRReg valueFPR = value.fpr();
+        JSValueRegs resultRegs = result.regs();
+
+#if CPU(X86)
+        // boxDouble() on X86 clobbers the source, so we need to copy.
+        // FIXME: Don't do that! https://bugs.webkit.org/show_bug.cgi?id=131690
+        FPRTemporary temp(this);
+        m_jit.moveDouble(valueFPR, temp.fpr());
+        valueFPR = temp.fpr();
+#endif
+        
+        boxDouble(valueFPR, resultRegs);
+        
+        jsValueResult(resultRegs, node);
+        return;
+    }
+        
+#if USE(JSVALUE64)
+    case Int52RepUse: {
+        SpeculateStrictInt52Operand value(this, node->child1());
+        GPRTemporary result(this);
+        
+        GPRReg valueGPR = value.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        boxInt52(valueGPR, resultGPR, DataFormatStrictInt52);
+        
+        jsValueResult(resultGPR, node);
+        return;
+    }
+#endif // USE(JSVALUE64)
+        
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
 }
 
 static double clampDoubleToByte(double d)
@@ -2320,7 +2387,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg propert
         }
             
 #if USE(JSVALUE64)
-        case MachineIntUse: {
+        case Int52RepUse: {
             SpeculateStrictInt52Operand valueOp(this, valueUse);
             GPRTemporary scratch(this);
             GPRReg scratchReg = scratch.gpr();
@@ -2344,7 +2411,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg propert
         }
 #endif // USE(JSVALUE64)
             
-        case NumberUse: {
+        case DoubleRepUse: {
             if (isClamped(type)) {
                 ASSERT(elementSize(type) == 1);
                 SpeculateDoubleOperand valueOp(this, valueUse);
@@ -2440,10 +2507,7 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType
         RELEASE_ASSERT_NOT_REACHED();
     }
     
-    MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
-    static const double NaN = QNaN;
-    m_jit.loadDouble(&NaN, resultReg);
-    notNaN.link(&m_jit);
+    m_jit.sanitizeDouble(resultReg);
     
     doubleResult(resultReg, node);
 }
@@ -2641,7 +2705,7 @@ void SpeculativeJIT::compileAdd(Node* node)
     }
         
 #if USE(JSVALUE64)
-    case MachineIntUse: {
+    case Int52RepUse: {
         ASSERT(shouldCheckOverflow(node->arithMode()));
         ASSERT(!shouldCheckNegativeZero(node->arithMode()));
 
@@ -2670,7 +2734,7 @@ void SpeculativeJIT::compileAdd(Node* node)
     }
 #endif // USE(JSVALUE64)
     
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         SpeculateDoubleOperand op2(this, node->child2());
         FPRTemporary result(this, op1, op2);
@@ -2807,7 +2871,7 @@ void SpeculativeJIT::compileArithSub(Node* node)
     }
         
 #if USE(JSVALUE64)
-    case MachineIntUse: {
+    case Int52RepUse: {
         ASSERT(shouldCheckOverflow(node->arithMode()));
         ASSERT(!shouldCheckNegativeZero(node->arithMode()));
 
@@ -2836,7 +2900,7 @@ void SpeculativeJIT::compileArithSub(Node* node)
     }
 #endif // USE(JSVALUE64)
 
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         SpeculateDoubleOperand op2(this, node->child2());
         FPRTemporary result(this, op1);
@@ -2881,7 +2945,7 @@ void SpeculativeJIT::compileArithNegate(Node* node)
     }
 
 #if USE(JSVALUE64)
-    case MachineIntUse: {
+    case Int52RepUse: {
         ASSERT(shouldCheckOverflow(node->arithMode()));
         
         if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)) {
@@ -2918,7 +2982,7 @@ void SpeculativeJIT::compileArithNegate(Node* node)
     }
 #endif // USE(JSVALUE64)
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         FPRTemporary result(this);
         
@@ -2969,7 +3033,7 @@ void SpeculativeJIT::compileArithMul(Node* node)
     }
     
 #if USE(JSVALUE64)   
-    case MachineIntUse: {
+    case Int52RepUse: {
         ASSERT(shouldCheckOverflow(node->arithMode()));
         
         // This is super clever. We want to do an int52 multiplication and check the
@@ -3026,7 +3090,7 @@ void SpeculativeJIT::compileArithMul(Node* node)
     }
 #endif // USE(JSVALUE64)
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         SpeculateDoubleOperand op2(this, node->child2());
         FPRTemporary result(this, op1, op2);
@@ -3190,7 +3254,7 @@ void SpeculativeJIT::compileArithDiv(Node* node)
         break;
     }
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         SpeculateDoubleOperand op2(this, node->child2());
         FPRTemporary result(this, op1);
@@ -3495,7 +3559,7 @@ void SpeculativeJIT::compileArithMod(Node* node)
         return;
     }
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand op1(this, node->child1());
         SpeculateDoubleOperand op2(this, node->child2());
         
@@ -3530,13 +3594,13 @@ bool SpeculativeJIT::compare(Node* node, MacroAssembler::RelationalCondition con
     }
     
 #if USE(JSVALUE64)
-    if (node->isBinaryUseKind(MachineIntUse)) {
+    if (node->isBinaryUseKind(Int52RepUse)) {
         compileInt52Compare(node, condition);
         return false;
     }
 #endif // USE(JSVALUE64)
     
-    if (node->isBinaryUseKind(NumberUse)) {
+    if (node->isBinaryUseKind(DoubleRepUse)) {
         compileDoubleCompare(node, doubleCondition);
         return false;
     }
@@ -3610,7 +3674,7 @@ bool SpeculativeJIT::compileStrictEq(Node* node)
     }
     
 #if USE(JSVALUE64)   
-    if (node->isBinaryUseKind(MachineIntUse)) {
+    if (node->isBinaryUseKind(Int52RepUse)) {
         unsigned branchIndexInBlock = detectPeepHoleBranch();
         if (branchIndexInBlock != UINT_MAX) {
             Node* branchNode = m_block->at(branchIndexInBlock);
@@ -3626,7 +3690,7 @@ bool SpeculativeJIT::compileStrictEq(Node* node)
     }
 #endif // USE(JSVALUE64)
 
-    if (node->isBinaryUseKind(NumberUse)) {
+    if (node->isBinaryUseKind(DoubleRepUse)) {
         unsigned branchIndexInBlock = detectPeepHoleBranch();
         if (branchIndexInBlock != UINT_MAX) {
             Node* branchNode = m_block->at(branchIndexInBlock);
@@ -4487,36 +4551,37 @@ void SpeculativeJIT::speculateInt32(Edge edge)
     (SpeculateInt32Operand(this, edge)).gpr();
 }
 
-void SpeculativeJIT::speculateMachineInt(Edge edge)
-{
-#if USE(JSVALUE64)
-    if (!needsTypeCheck(edge, SpecMachineInt))
-        return;
-    
-    (SpeculateWhicheverInt52Operand(this, edge)).gpr();
-#else // USE(JSVALUE64)
-    UNUSED_PARAM(edge);
-    UNREACHABLE_FOR_PLATFORM();
-#endif // USE(JSVALUE64)
-}
-
 void SpeculativeJIT::speculateNumber(Edge edge)
 {
-    if (!needsTypeCheck(edge, SpecFullNumber))
+    if (!needsTypeCheck(edge, SpecBytecodeNumber))
         return;
     
-    (SpeculateDoubleOperand(this, edge)).fpr();
+    JSValueOperand value(this, edge, ManualOperandSpeculation);
+#if USE(JSVALUE64)
+    GPRReg gpr = value.gpr();
+    typeCheck(
+        JSValueRegs(gpr), edge, SpecBytecodeNumber,
+        m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
+#else
+    GPRReg tagGPR = value.tagGPR();
+    DFG_TYPE_CHECK(
+        value.jsValueRegs(), edge, ~SpecInt32,
+        m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)));
+    DFG_TYPE_CHECK(
+        value.jsValueRegs(), edge, SpecBytecodeNumber,
+        m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
+#endif
 }
 
-void SpeculativeJIT::speculateRealNumber(Edge edge)
+void SpeculativeJIT::speculateDoubleReal(Edge edge)
 {
-    if (!needsTypeCheck(edge, SpecFullRealNumber))
+    if (!needsTypeCheck(edge, SpecDoubleReal))
         return;
     
     SpeculateDoubleOperand operand(this, edge);
     FPRReg fpr = operand.fpr();
-    DFG_TYPE_CHECK(
-        JSValueRegs(), edge, SpecFullRealNumber,
+    typeCheck(
+        JSValueRegs(), edge, SpecDoubleReal,
         m_jit.branchDouble(
             MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr));
 }
@@ -4768,8 +4833,11 @@ void SpeculativeJIT::speculate(Node*, Edge edge)
     case KnownInt32Use:
         ASSERT(!needsTypeCheck(edge, SpecInt32));
         break;
-    case KnownNumberUse:
-        ASSERT(!needsTypeCheck(edge, SpecFullNumber));
+    case DoubleRepUse:
+        ASSERT(!needsTypeCheck(edge, SpecDouble));
+        break;
+    case Int52RepUse:
+        ASSERT(!needsTypeCheck(edge, SpecMachineInt));
         break;
     case KnownCellUse:
         ASSERT(!needsTypeCheck(edge, SpecCell));
@@ -4780,15 +4848,12 @@ void SpeculativeJIT::speculate(Node*, Edge edge)
     case Int32Use:
         speculateInt32(edge);
         break;
-    case MachineIntUse:
-        speculateMachineInt(edge);
-        break;
-    case RealNumberUse:
-        speculateRealNumber(edge);
-        break;
     case NumberUse:
         speculateNumber(edge);
         break;
+    case DoubleRepRealUse:
+        speculateDoubleReal(edge);
+        break;
     case BooleanUse:
         speculateBoolean(edge);
         break;
index 00f4456..ef428ad 100644 (file)
@@ -54,7 +54,7 @@ class SpeculateDoubleOperand;
 class SpeculateCellOperand;
 class SpeculateBooleanOperand;
 
-enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandDouble, GeneratedOperandJSValue};
+enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandJSValue};
 
 inline GPRReg extractResult(GPRReg result) { return result; }
 #if USE(JSVALUE64)
@@ -190,7 +190,6 @@ public:
         if (spillMe.isValid()) {
 #if USE(JSVALUE32_64)
             GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
-            RELEASE_ASSERT(info.registerFormat() != DataFormatJSDouble);
             if ((info.registerFormat() & DataFormatJS))
                 m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR());
 #endif
@@ -265,7 +264,7 @@ public:
         else if (registerFormat != DataFormatNone)
             m_gprs.release(info.gpr());
 #elif USE(JSVALUE32_64)
-        if (registerFormat == DataFormatDouble || registerFormat == DataFormatJSDouble)
+        if (registerFormat == DataFormatDouble)
             m_fprs.release(info.fpr());
         else if (registerFormat & DataFormatJS) {
             m_gprs.release(info.tagGPR());
@@ -459,6 +458,10 @@ public:
         m_jit.unboxDouble(tagGPR, payloadGPR, fpr, scratchFPR);
     }
 #endif
+    void boxDouble(FPRReg fpr, JSValueRegs regs)
+    {
+        m_jit.boxDouble(fpr, regs);
+    }
 
     // Spill a VirtualRegister to the JSStack.
     void spill(VirtualRegister spillMe)
@@ -528,11 +531,10 @@ public:
             return;
         }
 
-        case DataFormatDouble:
-        case DataFormatJSDouble: {
+        case DataFormatDouble: {
             // On JSVALUE32_64 boxing a double is a no-op.
             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
-            info.spill(*m_stream, spillMe, DataFormatJSDouble);
+            info.spill(*m_stream, spillMe, DataFormatDouble);
             return;
         }
 
@@ -925,6 +927,14 @@ public:
         jsValueResult(tag, payload, node, DataFormatJS, mode);
     }
 #endif
+    void jsValueResult(JSValueRegs regs, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
+    {
+#if USE(JSVALUE64)
+        jsValueResult(regs.gpr(), node, format, mode);
+#else
+        jsValueResult(regs.tagGPR(), regs.payloadGPR(), node, format, mode);
+#endif
+    }
     void storageResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
     {
         if (mode == CallUseChildren)
@@ -2080,10 +2090,12 @@ public:
     
     void compileGetArrayLength(Node*);
     
+    void compileValueRep(Node*);
+    void compileDoubleRep(Node*);
+    
     void compileValueToInt32(Node*);
     void compileUInt32ToNumber(Node*);
     void compileDoubleAsInt32(Node*);
-    void compileInt32ToDouble(Node*);
     void compileAdd(Node*);
     void compileMakeRope(Node*);
     void compileArithSub(Node*);
@@ -2185,12 +2197,6 @@ public:
 
     void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements);
 
-#if USE(JSVALUE64) 
-    JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
-#elif USE(JSVALUE32_64)
-    JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result);
-#endif
-    
     // Add a speculation check.
     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
     void speculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail);
@@ -2217,7 +2223,7 @@ public:
     void speculateInt32(Edge);
     void speculateMachineInt(Edge);
     void speculateNumber(Edge);
-    void speculateRealNumber(Edge);
+    void speculateDoubleReal(Edge);
     void speculateBoolean(Edge);
     void speculateCell(Edge);
     void speculateObject(Edge);
@@ -2565,6 +2571,23 @@ private:
     GPRReg m_gpr;
 };
 
+class JSValueRegsTemporary {
+public:
+    JSValueRegsTemporary();
+    JSValueRegsTemporary(SpeculativeJIT*);
+    ~JSValueRegsTemporary();
+    
+    JSValueRegs regs();
+
+private:
+#if USE(JSVALUE64)
+    GPRTemporary m_gpr;
+#else
+    GPRTemporary m_payloadGPR;
+    GPRTemporary m_tagGPR;
+#endif
+};
+
 class FPRTemporary {
 public:
     FPRTemporary(SpeculativeJIT*);
@@ -2754,12 +2777,12 @@ private:
 // Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
 class SpeculateInt52Operand {
 public:
-    explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge)
         : m_jit(jit)
         , m_edge(edge)
         , m_gprOrInvalid(InvalidGPRReg)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         if (jit->isFilled(node()))
             gpr();
     }
@@ -2801,12 +2824,12 @@ private:
 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
 class SpeculateStrictInt52Operand {
 public:
-    explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge)
         : m_jit(jit)
         , m_edge(edge)
         , m_gprOrInvalid(InvalidGPRReg)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         if (jit->isFilled(node()))
             gpr();
     }
@@ -2849,35 +2872,35 @@ enum OppositeShiftTag { OppositeShift };
 
 class SpeculateWhicheverInt52Operand {
 public:
-    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge)
         : m_jit(jit)
         , m_edge(edge)
         , m_gprOrInvalid(InvalidGPRReg)
         , m_strict(jit->betterUseStrictInt52(edge))
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         if (jit->isFilled(node()))
             gpr();
     }
     
-    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other)
         : m_jit(jit)
         , m_edge(edge)
         , m_gprOrInvalid(InvalidGPRReg)
         , m_strict(other.m_strict)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         if (jit->isFilled(node()))
             gpr();
     }
     
-    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other)
         : m_jit(jit)
         , m_edge(edge)
         , m_gprOrInvalid(InvalidGPRReg)
         , m_strict(!other.m_strict)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         if (jit->isFilled(node()))
             gpr();
     }
@@ -2926,13 +2949,13 @@ private:
 
 class SpeculateDoubleOperand {
 public:
-    explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge)
         : m_jit(jit)
         , m_edge(edge)
         , m_fprOrInvalid(InvalidFPRReg)
     {
         ASSERT(m_jit);
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
+        RELEASE_ASSERT(isDouble(edge.useKind()));
         if (jit->isFilled(node()))
             fpr();
     }
index aaed79c..0dd9004 100644 (file)
@@ -134,20 +134,6 @@ bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR,
     }
 
     case DataFormatJSDouble:
-    case DataFormatDouble: {
-        FPRReg oldFPR = info.fpr();
-        m_fprs.lock(oldFPR);
-        tagGPR = allocate();
-        payloadGPR = allocate();
-        boxDouble(oldFPR, tagGPR, payloadGPR);
-        m_fprs.unlock(oldFPR);
-        m_fprs.release(oldFPR);
-        m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
-        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
-        info.fillJSValue(*m_stream, tagGPR, payloadGPR, DataFormatJS);
-        return true;
-    }
-
     case DataFormatJS:
     case DataFormatJSInt32:
     case DataFormatJSCell:
@@ -160,6 +146,7 @@ bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR,
     }
         
     case DataFormatStorage:
+    case DataFormatDouble:
         // this type currently never occurs
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -756,12 +743,6 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
     
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatDouble) {
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-            returnFormat = DataFormatInt32;
-            return allocate();
-        }
-        
         if (edge->hasConstant()) {
             ASSERT(isInt32Constant(edge.node()));
             GPRReg gpr = allocate();
@@ -813,7 +794,6 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         return gpr;
     }
 
-    case DataFormatDouble:
     case DataFormatCell:
     case DataFormatBoolean:
     case DataFormatJSDouble:
@@ -823,6 +803,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         returnFormat = DataFormatInt32;
         return allocate();
 
+    case DataFormatDouble:
     case DataFormatStorage:
     default:
         RELEASE_ASSERT_NOT_REACHED();
@@ -845,136 +826,34 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
 
 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
 {
-    AbstractValue& value = m_state.forNode(edge);
-    SpeculatedType type = value.m_type;
-    ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
-    m_interpreter.filter(value, SpecFullNumber);
+    ASSERT(isDouble(edge.useKind()));
+    ASSERT(edge->hasDoubleResult());
     VirtualRegister virtualRegister = edge->virtualRegister();
     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
 
     if (info.registerFormat() == DataFormatNone) {
 
         if (edge->hasConstant()) {
-            if (isInt32Constant(edge.node())) {
-                GPRReg gpr = allocate();
-                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr);
-                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-                info.fillInt32(*m_stream, gpr);
-                unlock(gpr);
-            } else if (isNumberConstant(edge.node())) {
-                FPRReg fpr = fprAllocate();
-                m_jit.loadDouble(addressOfDoubleConstant(edge.node()), fpr);
-                m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
-                info.fillDouble(*m_stream, fpr);
-                return fpr;
-            } else {
-                terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-                return fprAllocate();
-            }
-        } else {
-            DataFormat spillFormat = info.spillFormat();
-            ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
-            if (spillFormat == DataFormatJSDouble || spillFormat == DataFormatDouble) {
-                FPRReg fpr = fprAllocate();
-                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
-                m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
-                info.fillDouble(*m_stream, fpr);
-                return fpr;
-            }
-
+            RELEASE_ASSERT(isNumberConstant(edge.node()));
             FPRReg fpr = fprAllocate();
-            JITCompiler::Jump hasUnboxedDouble;
-
-            if (spillFormat != DataFormatJSInt32 && spillFormat != DataFormatInt32) {
-                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
-                if (type & ~SpecFullNumber)
-                    speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
-                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
-                hasUnboxedDouble = m_jit.jump();
-
-                isInteger.link(&m_jit);
-            }
-
-            m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
-
-            if (hasUnboxedDouble.isSet())
-                hasUnboxedDouble.link(&m_jit);
-
-            m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadDouble(addressOfDoubleConstant(edge.node()), fpr);
+            m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
             info.fillDouble(*m_stream, fpr);
-            info.killSpilled();
             return fpr;
         }
-    }
-
-    switch (info.registerFormat()) {
-    case DataFormatJS:
-    case DataFormatJSInt32: {
-        GPRReg tagGPR = info.tagGPR();
-        GPRReg payloadGPR = info.payloadGPR();
+        
+        RELEASE_ASSERT(info.spillFormat() == DataFormatDouble);
         FPRReg fpr = fprAllocate();
-
-        m_gprs.lock(tagGPR);
-        m_gprs.lock(payloadGPR);
-
-        JITCompiler::Jump hasUnboxedDouble;
-
-        if (info.registerFormat() != DataFormatJSInt32) {
-            FPRTemporary scratch(this);
-            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
-            if (type & ~SpecFullNumber)
-                speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
-            unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
-            hasUnboxedDouble = m_jit.jump();
-            isInteger.link(&m_jit);
-        }
-
-        m_jit.convertInt32ToDouble(payloadGPR, fpr);
-
-        if (hasUnboxedDouble.isSet())
-            hasUnboxedDouble.link(&m_jit);
-
-        m_gprs.release(tagGPR);
-        m_gprs.release(payloadGPR);
-        m_gprs.unlock(tagGPR);
-        m_gprs.unlock(payloadGPR);
-        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
         info.fillDouble(*m_stream, fpr);
-        info.killSpilled();
-        return fpr;
-    }
-
-    case DataFormatInt32: {
-        FPRReg fpr = fprAllocate();
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        m_jit.convertInt32ToDouble(gpr, fpr);
-        m_gprs.unlock(gpr);
-        return fpr;
-    }
-
-    case DataFormatJSDouble:
-    case DataFormatDouble: {
-        FPRReg fpr = info.fpr();
-        m_fprs.lock(fpr);
         return fpr;
     }
 
-    case DataFormatNone:
-    case DataFormatStorage:
-        RELEASE_ASSERT_NOT_REACHED();
-
-    case DataFormatCell:
-    case DataFormatJSCell:
-    case DataFormatBoolean:
-    case DataFormatJSBoolean:
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-        return fprAllocate();
-
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        return InvalidFPRReg;
-    }
+    RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
+    FPRReg fpr = info.fpr();
+    m_fprs.lock(fpr);
+    return fpr;
 }
 
 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
@@ -988,7 +867,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
+        if (info.spillFormat() == DataFormatInt32) {
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
             return allocate();
         }
@@ -1052,12 +931,12 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
     case DataFormatJSInt32:
     case DataFormatInt32:
     case DataFormatJSDouble:
-    case DataFormatDouble:
     case DataFormatJSBoolean:
     case DataFormatBoolean:
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
         return allocate();
 
+    case DataFormatDouble:
     case DataFormatStorage:
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -1077,7 +956,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
+        if (info.spillFormat() == DataFormatInt32) {
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
             return allocate();
         }
@@ -1133,12 +1012,12 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
     case DataFormatJSInt32:
     case DataFormatInt32:
     case DataFormatJSDouble:
-    case DataFormatDouble:
     case DataFormatJSCell:
     case DataFormatCell:
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
         return allocate();
 
+    case DataFormatDouble:
     case DataFormatStorage:
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -1148,28 +1027,6 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
     }
 }
 
-JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg result)
-{
-    FPRTemporary scratch(this);
-
-    GPRReg opPayloadGPR = op.payloadGPR();
-    GPRReg opTagGPR = op.tagGPR();
-    FPRReg scratchFPR = scratch.fpr();
-
-    JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, opTagGPR, TrustedImm32(JSValue::Int32Tag));
-    JITCompiler::Jump notNumber = m_jit.branch32(MacroAssembler::AboveOrEqual, opPayloadGPR, TrustedImm32(JSValue::LowestTag));
-
-    unboxDouble(opTagGPR, opPayloadGPR, result, scratchFPR);
-    JITCompiler::Jump done = m_jit.jump();
-
-    isInteger.link(&m_jit);
-    m_jit.convertInt32ToDouble(opPayloadGPR, result);
-
-    done.link(&m_jit);
-
-    return notNumber;
-}
-
 void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge)
 {
 #if ENABLE(GGC)
@@ -1547,7 +1404,7 @@ void SpeculativeJIT::compileLogicalNot(Node* node)
         return;
     }
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand value(this, node->child1());
         FPRTemporary scratch(this);
         GPRTemporary resultPayload(this);
@@ -1676,7 +1533,7 @@ void SpeculativeJIT::emitBranch(Node* node)
         return;
     }
     
-    case NumberUse:
+    case DoubleRepUse:
     case Int32Use: {
         if (node->child1().useKind() == Int32Use) {
             bool invert = false;
@@ -1817,6 +1674,7 @@ void SpeculativeJIT::compile(Node* node)
 
     switch (op) {
     case JSConstant:
+    case DoubleConstant:
         initConstantInfo(node);
         break;
 
@@ -1978,14 +1836,6 @@ void SpeculativeJIT::compile(Node* node)
             
         case FlushedJSValue:
         case FlushedArguments: {
-            if (generationInfoFromVirtualRegister(node->child1()->virtualRegister()).registerFormat() == DataFormatDouble) {
-                SpeculateDoubleOperand value(this, node->child1(), ManualOperandSpeculation);
-                m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
-                noResult(node);
-                recordSetLocal(DataFormatDouble);
-                break;
-            }
-            
             JSValueOperand value(this, node->child1());
             m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal()));
             m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal()));
@@ -2077,8 +1927,13 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
         
-    case Int32ToDouble: {
-        compileInt32ToDouble(node);
+    case DoubleRep: {
+        compileDoubleRep(node);
+        break;
+    }
+        
+    case ValueRep: {
+        compileValueRep(node);
         break;
     }
         
@@ -2151,7 +2006,7 @@ void SpeculativeJIT::compile(Node* node)
         }
         
             
-        case NumberUse: {
+        case DoubleRepUse: {
             SpeculateDoubleOperand op1(this, node->child1());
             FPRTemporary result(this);
             
@@ -2193,7 +2048,7 @@ void SpeculativeJIT::compile(Node* node)
             break;
         }
         
-        case NumberUse: {
+        case DoubleRepUse: {
             SpeculateDoubleOperand op1(this, node->child1());
             SpeculateDoubleOperand op2(this, node->child2());
             FPRTemporary result(this, op1);
@@ -4745,8 +4600,8 @@ void SpeculativeJIT::compile(Node* node)
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-    case Int52ToDouble:
-    case Int52ToValue:
+    case Int52Rep:
+    case Int52Constant:
     case CheckInBounds:
     case ArithIMul:
     case MultiGetByOffset:
index 3e69c43..2786730 100644 (file)
@@ -106,21 +106,9 @@ GPRReg SpeculativeJIT::fillJSValue(Edge edge)
                 break;
             }
                 
-            case DataFormatInt52:
-            case DataFormatStrictInt52: {
-                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-                boxInt52(gpr, gpr, spillFormat);
-                return gpr;
-            }
-                
             default:
                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-                if (spillFormat == DataFormatDouble) {
-                    // Need to box the double, since we want a JSValue.
-                    m_jit.sub64(GPRInfo::tagTypeNumberRegister, gpr);
-                    spillFormat = DataFormatJSDouble;
-                } else
-                    RELEASE_ASSERT(spillFormat & DataFormatJS);
+                RELEASE_ASSERT(spillFormat & DataFormatJS);
                 break;
             }
             info.fillJSValue(*m_stream, gpr, spillFormat);
@@ -143,28 +131,6 @@ GPRReg SpeculativeJIT::fillJSValue(Edge edge)
         return gpr;
     }
 
-    case DataFormatDouble: {
-        FPRReg fpr = info.fpr();
-        GPRReg gpr = boxDouble(fpr);
-
-        // Update all info
-        info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);
-        m_fprs.release(fpr);
-        m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
-
-        return gpr;
-    }
-        
-    case DataFormatInt52:
-    case DataFormatStrictInt52: {
-        GPRReg gpr = info.gpr();
-        lock(gpr);
-        GPRReg resultGPR = allocate();
-        boxInt52(gpr, resultGPR, info.registerFormat());
-        unlock(gpr);
-        return resultGPR;
-    }
-
     case DataFormatCell:
         // No retag required on JSVALUE64!
     case DataFormatJS:
@@ -179,6 +145,8 @@ GPRReg SpeculativeJIT::fillJSValue(Edge edge)
         
     case DataFormatBoolean:
     case DataFormatStorage:
+    case DataFormatDouble:
+    case DataFormatInt52:
         // this type currently never occurs
         RELEASE_ASSERT_NOT_REACHED();
         
@@ -769,12 +737,6 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
     
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatDouble) {
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-            returnFormat = DataFormatInt32;
-            return allocate();
-        }
-        
         GPRReg gpr = allocate();
 
         if (edge->hasConstant()) {
@@ -788,7 +750,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         
         DataFormat spillFormat = info.spillFormat();
         
-        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
+        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
         
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         
@@ -809,36 +771,6 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
             returnFormat = DataFormatJSInt32;
             return gpr;
         }
-        if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
-            // Generally, this can only happen if we've already proved that the
-            // value is an int32. That's because if a value originated as a JSValue
-            // then we would speculate that it's an int32 before representing it as
-            // an int52. Otherwise, if we knowingly produced an int52, then we would
-            // be boxing it into a value using Int52ToValue. This assertion is valid
-            // only because Int52 is something that we introduce at prediction time.
-            // However: we may have an int32-producing node replaced by an
-            // int52-producing node due to CSE. So we must do a check.
-            RELEASE_ASSERT(!(type & ~SpecMachineInt));
-            if (type & SpecInt52) {
-                GPRReg temp = allocate();
-                m_jit.signExtend32ToPtr(gpr, temp);
-                // Currently, we can't supply value profiling information here. :-/
-                speculationCheck(
-                    BadType, JSValueRegs(), 0,
-                    m_jit.branch64(MacroAssembler::NotEqual, gpr, temp));
-                unlock(temp);
-            }
-            if (spillFormat == DataFormatStrictInt52)
-                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
-            else {
-                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-                m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
-                m_jit.zeroExtend32ToPtr(gpr, gpr);
-            }
-            info.fillInt32(*m_stream, gpr);
-            returnFormat = DataFormatInt32;
-            return gpr;
-        }
         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
 
         // Fill as JSValue, and fall through.
@@ -897,47 +829,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         return gpr;
     }
         
-    case DataFormatStrictInt52:
-    case DataFormatInt52: {
-        GPRReg gpr = info.gpr();
-        GPRReg result;
-        DataFormat oldFormat = info.registerFormat();
-        if (m_gprs.isLocked(gpr)) {
-            result = allocate();
-            m_jit.move(gpr, result);
-        } else {
-            lock(gpr);
-            info.fillInt32(*m_stream, gpr);
-            result = gpr;
-        }
-        RELEASE_ASSERT(!(type & ~SpecMachineInt));
-        if (oldFormat == DataFormatInt52)
-            m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
-        if (type & SpecInt52) {
-            GPRReg temp = allocate();
-            m_jit.signExtend32ToPtr(result, temp);
-            // Currently, we can't supply value profiling information here. :-/
-            speculationCheck(
-                BadType, JSValueRegs(), 0,
-                m_jit.branch64(MacroAssembler::NotEqual, result, temp));
-            unlock(temp);
-        }
-        m_jit.zeroExtend32ToPtr(result, result);
-        returnFormat = DataFormatInt32;
-        return gpr;
-    }
-
-    case DataFormatDouble:
-    case DataFormatJSDouble: {
-        if (edge->hasConstant() && isInt32Constant(edge.node())) {
-            GPRReg gpr = allocate();
-            ASSERT(isInt32Constant(edge.node()));
-            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr);
-            returnFormat = DataFormatInt32;
-            return gpr;
-        }
-        FALLTHROUGH;
-    }
+    case DataFormatJSDouble:
     case DataFormatCell:
     case DataFormatBoolean:
     case DataFormatJSCell:
@@ -947,7 +839,10 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         return allocate();
     }
 
+    case DataFormatDouble:
     case DataFormatStorage:
+    case DataFormatInt52:
+    case DataFormatStrictInt52:
         RELEASE_ASSERT_NOT_REACHED();
         
     default:
@@ -976,14 +871,13 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
 {
     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
     AbstractValue& value = m_state.forNode(edge);
-    SpeculatedType type = value.m_type;
     m_interpreter.filter(value, SpecMachineInt);
     VirtualRegister virtualRegister = edge->virtualRegister();
     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) {
+        if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt())) {
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
             return allocate();
         }
@@ -1004,82 +898,21 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
         
         DataFormat spillFormat = info.spillFormat();
         
-        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
+        RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
         
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         
-        if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
-            // If we know this was spilled as an integer we can fill without checking.
-            m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
-            m_jit.signExtend32ToPtr(gpr, gpr);
-            if (desiredFormat == DataFormatStrictInt52) {
-                info.fillStrictInt52(*m_stream, gpr);
-                return gpr;
-            }
-            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
-            info.fillInt52(*m_stream, gpr);
-            return gpr;
-        }
-        if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
-            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-            if (desiredFormat == DataFormatStrictInt52) {
-                if (spillFormat == DataFormatInt52)
-                    m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
-                info.fillStrictInt52(*m_stream, gpr);
-                return gpr;
-            }
-            if (spillFormat == DataFormatStrictInt52)
-                m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
-            info.fillInt52(*m_stream, gpr);
-            return gpr;
-        }
         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-
-        // Fill as JSValue, and fall through.
-        info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
-        m_gprs.unlock(gpr);
-        FALLTHROUGH;
-    }
-
-    case DataFormatJS: {
-        // Check the value is an integer. Note that we would *like* to unbox an Int52
-        // at this point but this is too costly. We only *prove* that this is an Int52
-        // even though we check if it's an int32.
-        GPRReg gpr = info.gpr();
-        GPRReg result;
-        if (m_gprs.isLocked(gpr)) {
-            result = allocate();
-            m_jit.move(gpr, result);
-        } else {
-            m_gprs.lock(gpr);
-            result = gpr;
-        }
-        if (type & ~SpecInt32)
-            speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister));
-        if (result == gpr) // The not-already-locked, so fill in-place, case.
-            info.fillInt52(*m_stream, gpr, desiredFormat);
-        m_jit.signExtend32ToPtr(result, result);
-        if (desiredFormat == DataFormatInt52)
-            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
-        return result;
-    }
-
-    case DataFormatInt32:
-    case DataFormatJSInt32: {
-        GPRReg gpr = info.gpr();
-        GPRReg result;
-        if (m_gprs.isLocked(gpr)) {
-            result = allocate();
-            m_jit.move(gpr, result);
-        } else {
-            m_gprs.lock(gpr);
-            info.fillInt52(*m_stream, gpr, desiredFormat);
-            result = gpr;
+        if (desiredFormat == DataFormatStrictInt52) {
+            if (spillFormat == DataFormatInt52)
+                m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
+            info.fillStrictInt52(*m_stream, gpr);
+            return gpr;
         }
-        m_jit.signExtend32ToPtr(result, result);
-        if (desiredFormat == DataFormatInt52)
-            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
-        return result;
+        if (spillFormat == DataFormatStrictInt52)
+            m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
+        info.fillInt52(*m_stream, gpr);
+        return gpr;
     }
 
     case DataFormatStrictInt52: {
@@ -1116,31 +949,6 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
         return gpr;
     }
 
-    case DataFormatDouble:
-    case DataFormatJSDouble:
-        if (edge->hasConstant()) {
-            JSValue jsValue = valueOfJSConstant(edge.node());
-            if (jsValue.isMachineInt()) {
-                int64_t value = jsValue.asMachineInt();
-                if (desiredFormat == DataFormatInt52)
-                    value = value << JSValue::int52ShiftAmount;
-                GPRReg gpr = allocate();
-                m_jit.move(MacroAssembler::Imm64(value), gpr);
-                return gpr;
-            }
-        }
-        FALLTHROUGH;
-    case DataFormatCell:
-    case DataFormatBoolean:
-    case DataFormatJSCell:
-    case DataFormatJSBoolean: {
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-        return allocate();
-    }
-
-    case DataFormatStorage:
-        RELEASE_ASSERT_NOT_REACHED();
-        
     default:
         RELEASE_ASSERT_NOT_REACHED();
         return InvalidGPRReg;
@@ -1149,10 +957,8 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
 
 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
 {
-    AbstractValue& value = m_state.forNode(edge);
-    SpeculatedType type = value.m_type;
-    ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
-    m_interpreter.filter(value, SpecFullNumber);
+    ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse);
+    ASSERT(edge->hasDoubleResult());
     VirtualRegister virtualRegister = edge->virtualRegister();
     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
 
@@ -1160,17 +966,6 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
         if (edge->hasConstant()) {
             GPRReg gpr = allocate();
 
-            if (isInt32Constant(edge.node())) {
-                FPRReg fpr = fprAllocate();
-                m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant(edge.node())))), gpr);
-                m_jit.move64ToDouble(gpr, fpr);
-                unlock(gpr);
-
-                // Don't fill double here since that will lead to confusion: the
-                // register allocator will now think that this is a double while
-                // everyone else thinks it's an integer.
-                return fpr;
-            }
             if (isNumberConstant(edge.node())) {
                 FPRReg fpr = fprAllocate();
                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(edge.node()))), gpr);
@@ -1186,159 +981,18 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
         }
         
         DataFormat spillFormat = info.spillFormat();
-        switch (spillFormat) {
-        case DataFormatDouble: {
-            FPRReg fpr = fprAllocate();
-            m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
-            m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
-            info.fillDouble(*m_stream, fpr);
-            return fpr;
-        }
-            
-        case DataFormatInt32: {
-            GPRReg gpr = allocate();
-            
-            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-            m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
-            info.fillInt32(*m_stream, gpr);
-            unlock(gpr);
-            break;
-        }
-            
-        case DataFormatInt52: {
-            GPRReg gpr = allocate();
-            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-            info.fillInt52(*m_stream, gpr);
-            unlock(gpr);
-            break;
-        }
-            
-        case DataFormatStrictInt52: {
-            GPRReg gpr = allocate();
-            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-            info.fillStrictInt52(*m_stream, gpr);
-            unlock(gpr);
-            break;
-        }
-
-        default:
-            GPRReg gpr = allocate();
-
-            RELEASE_ASSERT(spillFormat & DataFormatJS);
-            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-            m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-            info.fillJSValue(*m_stream, gpr, spillFormat);
-            unlock(gpr);
-            break;
-        }
-    }
-
-    switch (info.registerFormat()) {
-    case DataFormatNone: // Should have filled, above.
-    case DataFormatBoolean: // This type never occurs.
-    case DataFormatStorage:
-        RELEASE_ASSERT_NOT_REACHED();
-
-    case DataFormatCell:
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-        return fprAllocate();
-
-    case DataFormatJSCell:
-    case DataFormatJS:
-    case DataFormatJSBoolean: {
-        GPRReg jsValueGpr = info.gpr();
-        m_gprs.lock(jsValueGpr);
+        RELEASE_ASSERT(spillFormat == DataFormatDouble);
         FPRReg fpr = fprAllocate();
-        GPRReg tempGpr = allocate();
-
-        JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
-
-        if (type & ~SpecFullNumber)
-            speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
-
-        // First, if we get here we have a double encoded as a JSValue
-        m_jit.move(jsValueGpr, tempGpr);
-        unboxDouble(tempGpr, fpr);
-        JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
-
-        // Finally, handle integers.
-        isInteger.link(&m_jit);
-        m_jit.convertInt32ToDouble(jsValueGpr, fpr);
-        hasUnboxedDouble.link(&m_jit);
-
-        m_gprs.release(jsValueGpr);
-        m_gprs.unlock(jsValueGpr);
-        m_gprs.unlock(tempGpr);
+        m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
         info.fillDouble(*m_stream, fpr);
-        info.killSpilled();
         return fpr;
     }
 
-    case DataFormatJSInt32:
-    case DataFormatInt32: {
-        FPRReg fpr = fprAllocate();
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        m_jit.convertInt32ToDouble(gpr, fpr);
-        m_gprs.unlock(gpr);
-        return fpr;
-    }
-        
-    case DataFormatInt52: {
-        FPRReg fpr = fprAllocate();
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        GPRReg temp = allocate();
-        m_jit.move(gpr, temp);
-        m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp);
-        m_jit.convertInt64ToDouble(temp, fpr);
-        unlock(temp);
-        m_gprs.unlock(gpr);
-        return fpr;
-    }
-        
-    case DataFormatStrictInt52: {
-        FPRReg fpr = fprAllocate();
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        m_jit.convertInt64ToDouble(gpr, fpr);
-        m_gprs.unlock(gpr);
-        return fpr;
-    }
-
-    // Unbox the double
-    case DataFormatJSDouble: {
-        GPRReg gpr = info.gpr();
-        FPRReg fpr = fprAllocate();
-        if (m_gprs.isLocked(gpr)) {
-            // Make sure we don't trample gpr if it is in use.
-            GPRReg temp = allocate();
-            m_jit.move(gpr, temp);
-            unboxDouble(temp, fpr);
-            unlock(temp);
-        } else
-            unboxDouble(gpr, fpr);
-
-        m_gprs.release(gpr);
-        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
-
-        info.fillDouble(*m_stream, fpr);
-        return fpr;
-    }
-
-    case DataFormatDouble: {
-        FPRReg fpr = info.fpr();
-        m_fprs.lock(fpr);
-        return fpr;
-    }
-        
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        return InvalidFPRReg;
-    }
+    RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
+    FPRReg fpr = info.fpr();
+    m_fprs.lock(fpr);
+    return fpr;
 }
 
 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
@@ -1352,11 +1006,6 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
-            return allocate();
-        }
-        
         GPRReg gpr = allocate();
 
         if (edge->hasConstant()) {
@@ -1405,16 +1054,16 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
     case DataFormatJSInt32:
     case DataFormatInt32:
     case DataFormatJSDouble:
-    case DataFormatDouble:
     case DataFormatJSBoolean:
-    case DataFormatBoolean:
-    case DataFormatInt52:
-    case DataFormatStrictInt52: {
+    case DataFormatBoolean: {
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
         return allocate();
     }
 
+    case DataFormatDouble:
     case DataFormatStorage:
+    case DataFormatInt52:
+    case DataFormatStrictInt52:
         RELEASE_ASSERT_NOT_REACHED();
         
     default:
@@ -1433,7 +1082,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
+        if (info.spillFormat() == DataFormatInt32) {
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
             return allocate();
         }
@@ -1487,16 +1136,15 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
     case DataFormatJSInt32:
     case DataFormatInt32:
     case DataFormatJSDouble:
-    case DataFormatDouble:
     case DataFormatJSCell:
     case DataFormatCell:
-    case DataFormatInt52:
-    case DataFormatStrictInt52: {
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
         return allocate();
-    }
         
+    case DataFormatDouble:
     case DataFormatStorage:
+    case DataFormatInt52:
+    case DataFormatStrictInt52:
         RELEASE_ASSERT_NOT_REACHED();
         
     default:
@@ -1505,26 +1153,6 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
     }
 }
 
-JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
-{
-    JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
-    
-    JITCompiler::Jump notNumber = m_jit.branchTest64(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
-    
-    m_jit.move(value, tmp);
-    unboxDouble(tmp, result);
-    
-    JITCompiler::Jump done = m_jit.jump();
-    
-    isInteger.link(&m_jit);
-    
-    m_jit.convertInt32ToDouble(value, result);
-    
-    done.link(&m_jit);
-
-    return notNumber;
-}
-
 void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge)
 {
 #if ENABLE(GGC)
@@ -1921,7 +1549,7 @@ void SpeculativeJIT::compileLogicalNot(Node* node)
         return;
     }
         
-    case NumberUse: {
+    case DoubleRepUse: {
         SpeculateDoubleOperand value(this, node->child1());
         FPRTemporary scratch(this);
         GPRTemporary result(this);
@@ -2060,7 +1688,7 @@ void SpeculativeJIT::emitBranch(Node* node)
     }
         
     case Int32Use:
-    case NumberUse: {
+    case DoubleRepUse: {
         if (node->child1().useKind() == Int32Use) {
             bool invert = false;
             
@@ -2153,6 +1781,8 @@ void SpeculativeJIT::compile(Node* node)
 
     switch (op) {
     case JSConstant:
+    case DoubleConstant:
+    case Int52Constant:
         initConstantInfo(node);
         break;
 
@@ -2400,24 +2030,23 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
         
-    case Int32ToDouble: {
-        compileInt32ToDouble(node);
+    case DoubleRep: {
+        compileDoubleRep(node);
         break;
     }
         
-    case Int52ToValue: {
-        JSValueOperand operand(this, node->child1());
-        GPRTemporary result(this, Reuse, operand);
-        m_jit.move(operand.gpr(), result.gpr());
-        jsValueResult(result.gpr(), node);
+    case ValueRep: {
+        compileValueRep(node);
         break;
     }
         
-    case Int52ToDouble: {
-        SpeculateDoubleOperand operand(this, node->child1());
-        FPRTemporary result(this, operand);
-        m_jit.moveDouble(operand.fpr(), result.fpr());
-        doubleResult(result.fpr(), node);
+    case Int52Rep: {
+        SpeculateInt32Operand operand(this, node->child1());
+        GPRTemporary result(this, Reuse, operand);
+        
+        m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
+        
+        strictInt52Result(result.gpr(), node);
         break;
     }
         
@@ -2486,7 +2115,7 @@ void SpeculativeJIT::compile(Node* node)
             break;
         }
         
-        case NumberUse: {
+        case DoubleRepUse: {
             SpeculateDoubleOperand op1(this, node->child1());
             FPRTemporary result(this);
             
@@ -2524,7 +2153,7 @@ void SpeculativeJIT::compile(Node* node)
             break;
         }
         
-        case NumberUse: {
+        case DoubleRepUse: {
             SpeculateDoubleOperand op1(this, node->child1());
             SpeculateDoubleOperand op2(this, node->child2());
             FPRTemporary result(this, op1);
index 68287fe..f67d8e7 100644 (file)
@@ -170,6 +170,62 @@ private:
             }
             break;
             
+        case ValueRep:
+        case Int52Rep:
+        case DoubleRep: {
+            // This short-circuits circuitous conversions, like ValueRep(DoubleRep(value)) or
+            // even more complicated things. Like, it can handle a beast like
+            // ValueRep(DoubleRep(Int52Rep(value))).
+            
+            // The only speculation that we would do beyond validating that we have a type that
+            // can be represented a certain way is an Int32 check that would appear on Int52Rep
+            // nodes. For now, if we see this and the final type we want is an Int52, we use it
+            // as an excuse not to fold. The only thing we would need is a Int52RepInt32Use kind.
+            bool hadInt32Check = false;
+            if (m_node->op() == Int52Rep) {
+                ASSERT(m_node->child1().useKind() == Int32Use);
+                hadInt32Check = true;
+            }
+            for (Node* node = m_node->child1().node(); ; node = node->child1().node()) {
+                if (canonicalResultRepresentation(node->result()) ==
+                    canonicalResultRepresentation(m_node->result())) {
+                    m_insertionSet.insertNode(
+                        m_nodeIndex, SpecNone, Phantom, m_node->origin, m_node->child1());
+                    if (hadInt32Check) {
+                        // FIXME: Consider adding Int52RepInt32Use or even DoubleRepInt32Use,
+                        // which would be super weird. The latter would only arise in some
+                        // seriously circuitous conversions.
+                        if (canonicalResultRepresentation(node->result()) != NodeResultJS)
+                            break;
+                        
+                        m_insertionSet.insertNode(
+                            m_nodeIndex, SpecNone, Phantom, m_node->origin,
+                            Edge(node, Int32Use));
+                    }
+                    m_node->child1() = node->defaultEdge();
+                    m_node->convertToIdentity();
+                    m_changed = true;
+                    break;
+                }
+                
+                switch (node->op()) {
+                case Int52Rep:
+                    ASSERT(node->child1().useKind() == Int32Use);
+                    hadInt32Check = true;
+                    continue;
+                    
+                case DoubleRep:
+                case ValueRep:
+                    continue;
+                    
+                default:
+                    break;
+                }
+                break;
+            }
+            break;
+        }
+            
         default:
             break;
         }
index 25c9fe9..4c9661d 100644 (file)
@@ -46,17 +46,17 @@ void printInternal(PrintStream& out, UseKind useKind)
     case KnownInt32Use:
         out.print("KnownInt32");
         break;
-    case MachineIntUse:
-        out.print("MachineInt");
-        break;
-    case RealNumberUse:
-        out.print("RealNumber");
+    case Int52RepUse:
+        out.print("Int52Rep");
         break;
     case NumberUse:
         out.print("Number");
         break;
-    case KnownNumberUse:
-        out.print("KnownNumber");
+    case DoubleRepUse:
+        out.print("DoubleRep");
+        break;
+    case DoubleRepRealUse:
+        out.print("DoubleRepReal");
         break;
     case BooleanUse:
         out.print("Boolean");
index 61bc923..533a985 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "DFGNodeFlags.h"
 #include "SpeculatedType.h"
 #include <wtf/PrintStream.h>
 
@@ -37,10 +38,10 @@ enum UseKind {
     UntypedUse,
     Int32Use,
     KnownInt32Use,
-    MachineIntUse,
-    RealNumberUse,
+    Int52RepUse,
     NumberUse,
-    KnownNumberUse,
+    DoubleRepUse,
+    DoubleRepRealUse,
     BooleanUse,
     CellUse,
     KnownCellUse,
@@ -59,7 +60,7 @@ enum UseKind {
     LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.
 };
 
-ALWAYS_INLINE SpeculatedType typeFilterFor(UseKind useKind)
+inline SpeculatedType typeFilterFor(UseKind useKind)
 {
     switch (useKind) {
     case UntypedUse:
@@ -67,13 +68,14 @@ ALWAYS_INLINE SpeculatedType typeFilterFor(UseKind useKind)
     case Int32Use:
     case KnownInt32Use:
         return SpecInt32;
-    case MachineIntUse:
+    case Int52RepUse:
         return SpecMachineInt;
-    case RealNumberUse:
-        return SpecFullRealNumber;
     case NumberUse:
-    case KnownNumberUse:
-        return SpecFullNumber;
+        return SpecBytecodeNumber;
+    case DoubleRepUse:
+        return SpecDouble;
+    case DoubleRepRealUse:
+        return SpecDoubleReal;
     case BooleanUse:
         return SpecBoolean;
     case CellUse:
@@ -108,53 +110,53 @@ ALWAYS_INLINE SpeculatedType typeFilterFor(UseKind useKind)
     }
 }
 
-ALWAYS_INLINE bool shouldNotHaveTypeCheck(UseKind kind)
+inline bool shouldNotHaveTypeCheck(UseKind kind)
 {
     switch (kind) {
     case UntypedUse:
     case KnownInt32Use:
-    case KnownNumberUse:
     case KnownCellUse:
     case KnownStringUse:
+    case Int52RepUse:
+    case DoubleRepUse:
         return true;
     default:
         return false;
     }
 }
 
-ALWAYS_INLINE bool mayHaveTypeCheck(UseKind kind)
+inline bool mayHaveTypeCheck(UseKind kind)
 {
     return !shouldNotHaveTypeCheck(kind);
 }
 
-ALWAYS_INLINE bool isNumerical(UseKind kind)
+inline bool isNumerical(UseKind kind)
 {
     switch (kind) {
     case Int32Use:
     case KnownInt32Use:
-    case MachineIntUse:
-    case RealNumberUse:
     case NumberUse:
-    case KnownNumberUse:
+    case Int52RepUse:
+    case DoubleRepUse:
+    case DoubleRepRealUse:
         return true;
     default:
         return false;
     }
 }
 
-ALWAYS_INLINE bool isDouble(UseKind kind)
+inline bool isDouble(UseKind kind)
 {
     switch (kind) {
-    case RealNumberUse:
-    case NumberUse:
-    case KnownNumberUse:
+    case DoubleRepUse:
+    case DoubleRepRealUse:
         return true;
     default:
         return false;
     }
 }
 
-ALWAYS_INLINE bool isCell(UseKind kind)
+inline bool isCell(UseKind kind)
 {
     switch (kind) {
     case CellUse:
@@ -174,7 +176,7 @@ ALWAYS_INLINE bool isCell(UseKind kind)
 
 // Returns true if it uses structure in a way that could be clobbered by
 // things that change the structure.
-ALWAYS_INLINE bool usesStructure(UseKind kind)
+inline bool usesStructure(UseKind kind)
 {
     switch (kind) {
     case StringObjectUse:
@@ -185,6 +187,19 @@ ALWAYS_INLINE bool usesStructure(UseKind kind)
     }
 }
 
+inline UseKind useKindForResult(NodeFlags result)
+{
+    ASSERT(!(result & ~NodeResultMask));
+    switch (result) {
+    case NodeResultInt52:
+        return Int52RepUse;
+    case NodeResultDouble:
+        return DoubleRepUse;
+    default:
+        return UntypedUse;
+    }
+}
+
 } } // namespace JSC::DFG
 
 namespace WTF {
index 361ff18..cfa4a0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -115,6 +115,9 @@ public:
                     
                     m_myRefCounts.find(edge.node())->value++;
                     
+                    VALIDATE((node, edge), edge->hasDoubleResult() == (edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse));
+                    VALIDATE((node, edge), edge->hasInt52Result() == (edge.useKind() == Int52RepUse));
+                    
                     if (m_graph.m_form == SSA) {
                         // In SSA, all edges must hasResult().
                         VALIDATE((node, edge), edge->hasResult());
diff --git a/Source/JavaScriptCore/dfg/DFGVariadicFunction.h b/Source/JavaScriptCore/dfg/DFGVariadicFunction.h
deleted file mode 100644 (file)
index f5523af..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef DFGVariadicFunction_h
-#define DFGVariadicFunction_h
-
-#define DFG_COMMA ,
-
-// The signature of v is (templatePre, templatePost, typeParams, valueParams, valueArgs)
-//
-// You would use it like:
-// #define DEFINE_FUNCTION(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs)
-//     templatePre typeParams templatePost void f(valueParams) { g(valueArgs); }
-// DFG_VARIADIC_TEMPLATE_FUNCTION(DEFINE_FUNCTION)
-// #undef DEFINE_FUNCTION
-//
-// Or if you wanted the defined function to take an additional template arg, you would do:
-// #define DEFINE_FUNCTION(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs)
-//     template<typename T valueParamsComma typeParams> void f(T value valueParamsComma valueParams) { g(value, valueArgs); }
-// DFG_VARIADIC_TEMPLATE_FUNCTION(DEFINE_FUNCTION)
-// #undef DEFINE_FUNCTION
-
-#define DFG_VARIADIC_TEMPLATE_FUNCTION(v) \
-    v(, , , , , ) \
-    v(template<, >, typename _DFG_T1, DFG_COMMA, const _DFG_T1& _DFG_value1, _DFG_value1) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2, _DFG_value1 DFG_COMMA _DFG_value2) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3 DFG_COMMA typename _DFG_T4, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3 DFG_COMMA const _DFG_T4& _DFG_value4, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3 DFG_COMMA _DFG_value4) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3 DFG_COMMA typename _DFG_T4 DFG_COMMA typename _DFG_T5, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3 DFG_COMMA const _DFG_T4& _DFG_value4 DFG_COMMA const _DFG_T5& _DFG_value5, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3 DFG_COMMA _DFG_value4 DFG_COMMA _DFG_value5) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3 DFG_COMMA typename _DFG_T4 DFG_COMMA typename _DFG_T5 DFG_COMMA typename _DFG_T6, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3 DFG_COMMA const _DFG_T4& _DFG_value4 DFG_COMMA const _DFG_T5& _DFG_value5 DFG_COMMA const _DFG_T6& _DFG_value6, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3 DFG_COMMA _DFG_value4 DFG_COMMA _DFG_value5 DFG_COMMA _DFG_value6) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3 DFG_COMMA typename _DFG_T4 DFG_COMMA typename _DFG_T5 DFG_COMMA typename _DFG_T6 DFG_COMMA typename _DFG_T7, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3 DFG_COMMA const _DFG_T4& _DFG_value4 DFG_COMMA const _DFG_T5& _DFG_value5 DFG_COMMA const _DFG_T6& _DFG_value6 DFG_COMMA const _DFG_T7& _DFG_value7, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3 DFG_COMMA _DFG_value4 DFG_COMMA _DFG_value5 DFG_COMMA _DFG_value6 DFG_COMMA _DFG_value7) \
-    v(template<, >, typename _DFG_T1 DFG_COMMA typename _DFG_T2 DFG_COMMA typename _DFG_T3 DFG_COMMA typename _DFG_T4 DFG_COMMA typename _DFG_T5 DFG_COMMA typename _DFG_T6 DFG_COMMA typename _DFG_T7 DFG_COMMA typename _DFG_T8, DFG_COMMA, const _DFG_T1& _DFG_value1 DFG_COMMA const _DFG_T2& _DFG_value2 DFG_COMMA const _DFG_T3& _DFG_value3 DFG_COMMA const _DFG_T4& _DFG_value4 DFG_COMMA const _DFG_T5& _DFG_value5 DFG_COMMA const _DFG_T6& _DFG_value6 DFG_COMMA const _DFG_T7& _DFG_value7 DFG_COMMA _DFG_T8& _DFG_value8, _DFG_value1 DFG_COMMA _DFG_value2 DFG_COMMA _DFG_value3 DFG_COMMA _DFG_value4 DFG_COMMA _DFG_value5 DFG_COMMA _DFG_value6 DFG_COMMA _DFG_value7 DFG_COMMA _DFG_value8)
-
-#endif // DFGVariadicFunction_h
-
index 91cfc41..9ef18be 100644 (file)
@@ -90,7 +90,6 @@ inline CapabilityLevel canCompile(Node* node)
     case ArithFRound:
     case ArithNegate:
     case UInt32ToNumber:
-    case Int32ToDouble:
     case CompareEqConstant:
     case Jump:
     case ForceOSRExit:
@@ -103,7 +102,6 @@ inline CapabilityLevel canCompile(Node* node)
     case GetClosureRegisters:
     case GetClosureVar:
     case PutClosureVar:
-    case Int52ToValue:
     case InvalidationPoint:
     case StringCharAt:
     case CheckFunction:
@@ -152,8 +150,19 @@ inline CapabilityLevel canCompile(Node* node)
     case IsFunction:
     case CheckHasInstance:
     case InstanceOf:
+    case DoubleRep:
+    case ValueRep:
+    case Int52Rep:
+    case DoubleConstant:
+    case Int52Constant:
         // These are OK.
         break;
+    case Identity:
+        // No backend handles this because it will be optimized out. But we may check
+        // for capabilities before optimization. It would be a deep error to remove this
+        // case because it would prevent us from catching bugs where the FTL backend
+        // pipeline failed to optimize out an Identity.
+        break;
     case PutByIdDirect:
     case PutById:
         if (node->child1().useKind() == CellUse)
@@ -235,9 +244,9 @@ inline CapabilityLevel canCompile(Node* node)
     case CompareEq:
         if (node->isBinaryUseKind(Int32Use))
             break;
-        if (node->isBinaryUseKind(MachineIntUse))
+        if (node->isBinaryUseKind(Int52RepUse))
             break;
-        if (node->isBinaryUseKind(NumberUse))
+        if (node->isBinaryUseKind(DoubleRepUse))
             break;
         if (node->isBinaryUseKind(StringIdentUse))
             break;
@@ -255,9 +264,9 @@ inline CapabilityLevel canCompile(Node* node)
     case CompareStrictEq:
         if (node->isBinaryUseKind(Int32Use))
             break;
-        if (node->isBinaryUseKind(MachineIntUse))
+        if (node->isBinaryUseKind(Int52RepUse))
             break;
-        if (node->isBinaryUseKind(NumberUse))
+        if (node->isBinaryUseKind(DoubleRepUse))
             break;
         if (node->isBinaryUseKind(StringIdentUse))
             break;
@@ -280,9 +289,9 @@ inline CapabilityLevel canCompile(Node* node)
     case CompareGreaterEq:
         if (node->isBinaryUseKind(Int32Use))
             break;
-        if (node->isBinaryUseKind(MachineIntUse))
+        if (node->isBinaryUseKind(Int52RepUse))
             break;
-        if (node->isBinaryUseKind(NumberUse))
+        if (node->isBinaryUseKind(DoubleRepUse))
             break;
         if (node->isBinaryUseKind(UntypedUse))
             break;
@@ -350,10 +359,10 @@ CapabilityLevel canCompile(Graph& graph)
                 case UntypedUse:
                 case Int32Use:
                 case KnownInt32Use:
-                case MachineIntUse:
+                case Int52RepUse:
                 case NumberUse:
-                case KnownNumberUse:
-                case RealNumberUse:
+                case DoubleRepUse:
+                case DoubleRepRealUse:
                 case BooleanUse:
                 case CellUse:
                 case KnownCellUse:
index 2cf8c81..84bc0ea 100644 (file)
@@ -186,7 +186,7 @@ private:
                     continue;
                 LType type;
                 switch (node->flags() & NodeResultMask) {
-                case NodeResultNumber:
+                case NodeResultDouble:
                     type = m_out.doubleType;
                     break;
                 case NodeResultInt32:
@@ -282,12 +282,30 @@ private:
             break;
         case JSConstant:
             break;
+        case DoubleConstant:
+            compileDoubleConstant();
+            break;
+        case Int52Constant:
+            compileInt52Constant();
+            break;
         case WeakJSConstant:
             compileWeakJSConstant();
             break;
         case PhantomArguments:
             compilePhantomArguments();
             break;
+        case DoubleRep:
+            compileDoubleRep();
+            break;
+        case ValueRep:
+            compileValueRep();
+            break;
+        case Int52Rep:
+            compileInt52Rep();
+            break;
+        case ValueToInt32:
+            compileValueToInt32();
+            break;
         case GetArgument:
             compileGetArgument();
             break;
@@ -378,9 +396,6 @@ private:
         case UInt32ToNumber:
             compileUInt32ToNumber();
             break;
-        case Int32ToDouble:
-            compileInt32ToDouble();
-            break;
         case CheckStructure:
             compileCheckStructure();
             break;
@@ -569,12 +584,6 @@ private:
         case InvalidationPoint:
             compileInvalidationPoint();
             break;
-        case ValueToInt32:
-            compileValueToInt32();
-            break;
-        case Int52ToValue:
-            compileInt52ToValue();
-            break;
         case CheckArgumentsNotCreated:
             compileCheckArgumentsNotCreated();
             break;
@@ -633,73 +642,18 @@ private:
         return true;
     }
 
-    void compileValueToInt32()
-    {
-        switch (m_node->child1().useKind()) {
-        case Int32Use:
-            setInt32(lowInt32(m_node->child1()));
-            break;
-            
-        case MachineIntUse:
-            setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
-            break;
-            
-        case NumberUse:
-        case NotCellUse: {
-            LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
-            if (isValid(value)) {
-                setInt32(value.value());
-                break;
-            }
-            
-            value = m_jsValueValues.get(m_node->child1().node());
-            if (isValid(value)) {
-                setInt32(numberOrNotCellToInt32(m_node->child1(), value.value()));
-                break;
-            }
-            
-            value = m_doubleValues.get(m_node->child1().node());
-            if (isValid(value)) {
-                setInt32(doubleToInt32(value.value()));
-                break;
-            }
-            
-            // We'll basically just get here for constants. But it's good to have this
-            // catch-all since we often add new representations into the mix.
-            setInt32(
-                numberOrNotCellToInt32(
-                    m_node->child1(),
-                    lowJSValue(m_node->child1(), ManualOperandSpeculation)));
-            break;
-        }
-            
-        case BooleanUse:
-            setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
-            break;
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-    }
-
-    void compileInt52ToValue()
-    {
-        setJSValue(lowJSValue(m_node->child1()));
-    }
-
     void compileUpsilon()
     {
         LValue destination = m_phis.get(m_node->phi());
         
         switch (m_node->child1().useKind()) {
-        case NumberUse:
+        case DoubleRepUse:
             m_out.set(lowDouble(m_node->child1()), destination);
             break;
         case Int32Use:
             m_out.set(lowInt32(m_node->child1()), destination);
             break;
-        case MachineIntUse:
+        case Int52RepUse:
             m_out.set(lowInt52(m_node->child1()), destination);
             break;
         case BooleanUse:
@@ -722,7 +676,7 @@ private:
         LValue source = m_phis.get(m_node);
         
         switch (m_node->flags() & NodeResultMask) {
-        case NodeResultNumber:
+        case NodeResultDouble:
             setDouble(m_out.get(source));
             break;
         case NodeResultInt32:
@@ -742,17 +696,120 @@ private:
             break;
         }
     }
+    
+    void compileDoubleConstant()
+    {
+        setDouble(m_out.constDouble(m_graph.valueOfNumberConstant(m_node)));
+    }
+    
+    void compileInt52Constant()
+    {
+        int64_t value = m_graph.valueOfJSConstant(m_node).asMachineInt();
+        
+        setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount));
+        setStrictInt52(m_out.constInt64(value));
+    }
 
+    void compileWeakJSConstant()
+    {
+        setJSValue(weakPointer(m_node->weakConstant()));
+    }
+    
     void compilePhantomArguments()
     {
         setJSValue(m_out.constInt64(JSValue::encode(JSValue())));
     }
     
-    void compileWeakJSConstant()
+    void compileDoubleRep()
     {
-        setJSValue(weakPointer(m_node->weakConstant()));
+        switch (m_node->child1().useKind()) {
+        case NumberUse: {
+            LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
+            setDouble(jsValueToDouble(m_node->child1(), value));
+            return;
+        }
+            
+        case Int52RepUse: {
+            setDouble(strictInt52ToDouble(lowStrictInt52(m_node->child1())));
+            return;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    }
+    
+    void compileValueRep()
+    {
+        switch (m_node->child1().useKind()) {
+        case DoubleRepUse: {
+            setJSValue(boxDouble(lowDouble(m_node->child1())));
+            return;
+        }
+            
+        case Int52RepUse: {
+            setJSValue(strictInt52ToJSValue(lowStrictInt52(m_node->child1())));
+            return;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
     }
     
+    void compileInt52Rep()
+    {
+        setStrictInt52(m_out.signExt(lowInt32(m_node->child1()), m_out.int64));
+    }
+    
+    void compileValueToInt32()
+    {
+        switch (m_node->child1().useKind()) {
+        case Int32Use:
+            setInt32(lowInt32(m_node->child1()));
+            break;
+            
+        case Int52RepUse:
+            setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
+            break;
+            
+        case DoubleRepUse:
+            setInt32(doubleToInt32(lowDouble(m_node->child1())));
+            break;
+            
+        case NumberUse:
+        case NotCellUse: {
+            LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
+            if (isValid(value)) {
+                setInt32(value.value());
+                break;
+            }
+            
+            value = m_jsValueValues.get(m_node->child1().node());
+            if (isValid(value)) {
+                setInt32(numberOrNotCellToInt32(m_node->child1(), value.value()));
+                break;
+            }
+            
+            // We'll basically just get here for constants. But it's good to have this
+            // catch-all since we often add new representations into the mix.
+            setInt32(
+                numberOrNotCellToInt32(
+                    m_node->child1(),
+                    lowJSValue(m_node->child1(), ManualOperandSpeculation)));
+            break;
+        }
+            
+        case BooleanUse:
+            setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
+            break;
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+
     void compileGetArgument()
     {
         VariableAccessData* variable = m_node->variableAccessData();
@@ -966,7 +1023,7 @@ private:
             break;
         }
             
-        case MachineIntUse: {
+        case Int52RepUse: {
             if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
                 && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
                 Int52Kind kind;
@@ -1016,7 +1073,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             LValue C1 = lowDouble(m_node->child1());
             LValue C2 = lowDouble(m_node->child2());
 
@@ -1065,7 +1122,7 @@ private:
             break;
         }
             
-        case MachineIntUse: {
+        case Int52RepUse: {
             Int52Kind kind;
             LValue left = lowWhicheverInt52(m_node->child1(), kind);
             LValue right = lowInt52(m_node->child2(), opposite(kind));
@@ -1092,7 +1149,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             setDouble(
                 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
             break;
@@ -1195,7 +1252,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             setDouble(m_out.doubleDiv(
                 lowDouble(m_node->child1()), lowDouble(m_node->child2())));
             break;
@@ -1293,7 +1350,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             setDouble(
                 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
             break;
@@ -1321,7 +1378,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             LValue left = lowDouble(m_node->child1());
             LValue right = lowDouble(m_node->child2());
             
@@ -1371,7 +1428,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
             break;
         }
@@ -1418,7 +1475,7 @@ private:
             break;
         }
             
-        case MachineIntUse: {
+        case Int52RepUse: {
             if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) {
                 Int52Kind kind;
                 LValue value = lowWhicheverInt52(m_node->child1(), kind);
@@ -1438,7 +1495,7 @@ private:
             break;
         }
             
-        case NumberUse: {
+        case DoubleRepUse: {
             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
             break;
         }
@@ -1498,11 +1555,6 @@ private:
         setInt32(value);
     }
     
-    void compileInt32ToDouble()
-    {
-        setDouble(lowDouble(m_node->child1()));
-    }
-    
     void compileCheckStructure()
     {
         LValue cell = lowCell(m_node->child1());
@@ -2213,7 +2265,7 @@ private:
                 if (isInt(type)) {
                     LValue intValue;
                     switch (child3.useKind()) {
-                    case MachineIntUse:
+                    case Int52RepUse:
                     case Int32Use: {
                         if (child3.useKind() == Int32Use)
                             intValue = lowInt32(child3);
@@ -2246,7 +2298,7 @@ private:
                         break;
                     }
                         
-                    case NumberUse: {
+                    case DoubleRepUse: {
                         LValue doubleValue = lowDouble(child3);
                         
                         if (isClamped(type)) {
@@ -3328,8 +3380,8 @@ private:
     void compileCompareEq()
     {
         if (m_node->isBinaryUseKind(Int32Use)
-            || m_node->isBinaryUseKind(MachineIntUse)
-            || m_node->isBinaryUseKind(NumberUse)
+            || m_node->isBinaryUseKind(Int52RepUse)
+            || m_node->isBinaryUseKind(DoubleRepUse)
             || m_node->isBinaryUseKind(ObjectUse)
             || m_node->isBinaryUseKind(BooleanUse)
             || m_node->isBinaryUseKind(StringIdentUse)) {
@@ -3371,7 +3423,7 @@ private:
             return;
         }
         
-        if (m_node->isBinaryUseKind(MachineIntUse)) {
+        if (m_node->isBinaryUseKind(Int52RepUse)) {
             Int52Kind kind;
             LValue left = lowWhicheverInt52(m_node->child1(), kind);
             LValue right = lowInt52(m_node->child2(), kind);
@@ -3379,7 +3431,7 @@ private:
             return;
         }
         
-        if (m_node->isBinaryUseKind(NumberUse)) {
+        if (m_node->isBinaryUseKind(DoubleRepUse)) {
             setBoolean(
                 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
             return;
@@ -4123,7 +4175,7 @@ private:
             return;
         }
         
-        if (m_node->isBinaryUseKind(MachineIntUse)) {
+        if (m_node->isBinaryUseKind(Int52RepUse)) {
             Int52Kind kind;
             LValue left = lowWhicheverInt52(m_node->child1(), kind);
             LValue right = lowInt52(m_node->child2(), kind);
@@ -4131,7 +4183,7 @@ private:
             return;
         }
         
-        if (m_node->isBinaryUseKind(NumberUse)) {
+        if (m_node->isBinaryUseKind(DoubleRepUse)) {
             LValue left = lowDouble(m_node->child1());
             LValue right = lowDouble(m_node->child2());
             setBoolean(m_out.fcmp(realCondition, left, right));
@@ -4388,7 +4440,7 @@ private:
             return lowBoolean(m_node->child1());
         case Int32Use:
             return m_out.notZero32(lowInt32(m_node->child1()));
-        case NumberUse:
+        case DoubleRepUse:
             return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
         case ObjectOrOtherUse:
             return m_out.bitNot(
@@ -4734,21 +4786,9 @@ private:
     }
     
     enum Int52Kind { StrictInt52, Int52 };
-    LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    LValue lowInt52(Edge edge, Int52Kind kind)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
-        
-        if (edge->hasConstant()) {
-            JSValue value = m_graph.valueOfJSConstant(edge.node());
-            if (!value.isMachineInt()) {
-                terminate(Uncountable);
-                return m_out.int64Zero;
-            }
-            int64_t result = value.asMachineInt();
-            if (kind == Int52)
-                result <<= JSValue::int52ShiftAmount;
-            return m_out.constInt64(result);
-        }
+        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
         
         LoweredNodeValue value;
         
@@ -4773,37 +4813,20 @@ private:
                 return int52ToStrictInt52(value.value());
             break;
         }
-        
-        value = m_int32Values.get(edge.node());
-        if (isValid(value)) {
-            return setInt52WithStrictValue(
-                edge.node(), m_out.signExt(value.value(), m_out.int64), kind);
-        }
-        
-        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52));
-        
-        value = m_jsValueValues.get(edge.node());
-        if (isValid(value)) {
-            LValue boxedResult = value.value();
-            FTL_TYPE_CHECK(
-                jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult));
-            return setInt52WithStrictValue(
-                edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind);
-        }
-        
-        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt));
+
+        RELEASE_ASSERT(!m_state.forNode(edge).m_type);
         terminate(Uncountable);
         return m_out.int64Zero;
     }
     
-    LValue lowInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    LValue lowInt52(Edge edge)
     {
-        return lowInt52(edge, Int52, mode);
+        return lowInt52(edge, Int52);
     }
     
-    LValue lowStrictInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    LValue lowStrictInt52(Edge edge)
     {
-        return lowInt52(edge, StrictInt52, mode);
+        return lowInt52(edge, StrictInt52);
     }
     
     bool betterUseStrictInt52(Node* node)
@@ -4830,10 +4853,10 @@ private:
         RELEASE_ASSERT_NOT_REACHED();
     }
     
-    LValue lowWhicheverInt52(Edge edge, Int52Kind& kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    LValue lowWhicheverInt52(Edge edge, Int52Kind& kind)
     {
         kind = bestInt52Kind(edge);
-        return lowInt52(edge, kind, mode);
+        return lowInt52(edge, kind);
     }
     
     LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
@@ -4931,71 +4954,15 @@ private:
         return m_out.booleanFalse;
     }
     
-    LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    LValue lowDouble(Edge edge)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
-        
-        if (edge->hasConstant()) {
-            JSValue value = m_graph.valueOfJSConstant(edge.node());
-            if (!value.isNumber()) {
-                terminate(Uncountable);
-                return m_out.doubleZero;
-            }
-            return m_out.constDouble(value.asNumber());
-        }
+        RELEASE_ASSERT(isDouble(edge.useKind()));
         
         LoweredNodeValue value = m_doubleValues.get(edge.node());
         if (isValid(value))
             return value.value();
         
-        value = m_int32Values.get(edge.node());
-        if (isValid(value)) {
-            LValue result = m_out.intToDouble(value.value());
-            setDouble(edge.node(), result);
-            return result;
-        }
-        
-        value = m_strictInt52Values.get(edge.node());
-        if (isValid(value))
-            return strictInt52ToDouble(edge, value.value());
-        
-        value = m_int52Values.get(edge.node());
-        if (isValid(value))
-            return strictInt52ToDouble(edge, int52ToStrictInt52(value.value()));
-        
-        value = m_jsValueValues.get(edge.node());
-        if (isValid(value)) {
-            LValue boxedResult = value.value();
-            
-            LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
-            LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
-            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
-            
-            m_out.branch(isNotInt32(boxedResult), unsure(doubleCase), unsure(intCase));
-            
-            LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
-            
-            ValueFromBlock intToDouble = m_out.anchor(
-                m_out.intToDouble(unboxInt32(boxedResult)));
-            m_out.jump(continuation);
-            
-            m_out.appendTo(doubleCase, continuation);
-            
-            FTL_TYPE_CHECK(
-                jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult));
-            
-            ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
-            m_out.jump(continuation);
-            
-            m_out.appendTo(continuation, lastNext);
-            
-            LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
-            
-            setDouble(edge.node(), result);
-            return result;
-        }
-        
-        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber));
+        RELEASE_ASSERT(!m_state.forNode(edge).m_type);
         terminate(Uncountable);
         return m_out.doubleZero;
     }
@@ -5003,6 +4970,8 @@ private:
     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     {
         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
+        RELEASE_ASSERT(!isDouble(edge.useKind()));
+        RELEASE_ASSERT(edge.useKind() != Int52RepUse);
         
         if (edge->hasConstant())
             return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node())));
@@ -5018,14 +4987,6 @@ private:
             return result;
         }
         
-        value = m_strictInt52Values.get(edge.node());
-        if (isValid(value))
-            return strictInt52ToJSValue(value.value());
-        
-        value = m_int52Values.get(edge.node());
-        if (isValid(value))
-            return strictInt52ToJSValue(int52ToStrictInt52(value.value()));
-        
         value = m_booleanValues.get(edge.node());
         if (isValid(value)) {
             LValue result = boxBoolean(value.value());
@@ -5033,13 +4994,6 @@ private:
             return result;
         }
         
-        value = m_doubleValues.get(edge.node());
-        if (isValid(value)) {
-            LValue result = boxDouble(value.value());
-            setJSValue(edge.node(), result);
-            return result;
-        }
-        
         RELEASE_ASSERT_NOT_REACHED();
         return 0;
     }
@@ -5065,11 +5019,9 @@ private:
         return result;
     }
     
-    LValue strictInt52ToDouble(Edge edge, LValue value)
+    LValue strictInt52ToDouble(LValue value)
     {
-        LValue result = m_out.intToDouble(value);
-        setDouble(edge.node(), result);
-        return result;
+        return m_out.intToDouble(value);
     }
     
     LValue strictInt52ToJSValue(LValue value)
@@ -5099,23 +5051,6 @@ private:
         return m_out.phi(m_out.int64, results);
     }
     
-    LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind)
-    {
-        switch (kind) {
-        case StrictInt52:
-            setStrictInt52(node, value);
-            return value;
-            
-        case Int52:
-            value = strictInt52ToInt52(value);
-            setInt52(node, value);
-            return value;
-        }
-        
-        RELEASE_ASSERT_NOT_REACHED();
-        return 0;
-    }
-
     LValue strictInt52ToInt52(LValue value)
     {
         return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
@@ -5147,6 +5082,7 @@ private:
     {
         return m_out.testNonZero64(jsValue, m_tagTypeNumber);
     }
+    
     LValue unboxDouble(LValue jsValue)
     {
         return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
@@ -5155,6 +5091,39 @@ private:
     {
         return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
     }
+    LValue jsValueToDouble(Edge edge, LValue boxedValue)
+    {
+        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing int case"));
+        LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing double case"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing continuation"));
+            
+        LValue isNotInt32;
+        if (!m_interpreter.needsTypeCheck(edge, SpecInt32))
+            isNotInt32 = m_out.booleanFalse;
+        else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32))
+            isNotInt32 = m_out.booleanTrue;
+        else
+            isNotInt32 = this->isNotInt32(boxedValue);
+        m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase));
+            
+        LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
+            
+        ValueFromBlock intToDouble = m_out.anchor(
+            m_out.intToDouble(unboxInt32(boxedValue)));
+        m_out.jump(continuation);
+            
+        m_out.appendTo(doubleCase, continuation);
+            
+        FTL_TYPE_CHECK(
+            jsValueValue(boxedValue), edge, SpecBytecodeNumber, isCellOrMisc(boxedValue));
+            
+        ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
+        m_out.jump(continuation);
+            
+        m_out.appendTo(continuation, lastNext);
+            
+        return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
+    }
     
     LValue isNumber(LValue jsValue)
     {
@@ -5226,8 +5195,9 @@ private:
         case UntypedUse:
             break;
         case KnownInt32Use:
-        case KnownNumberUse:
         case KnownStringUse:
+        case DoubleRepUse:
+        case Int52RepUse:
             ASSERT(!m_interpreter.needsTypeCheck(edge));
             break;
         case Int32Use:
@@ -5260,14 +5230,11 @@ private:
         case StringOrStringObjectUse:
             speculateStringOrStringObject(edge);
             break;
-        case RealNumberUse:
-            speculateRealNumber(edge);
-            break;
         case NumberUse:
             speculateNumber(edge);
             break;
-        case MachineIntUse:
-            speculateMachineInt(edge);
+        case DoubleRepRealUse:
+            speculateDoubleReal(edge);
             break;
         case BooleanUse:
             speculateBoolean(edge);
@@ -5529,14 +5496,11 @@ private:
     
     void speculateNumber(Edge edge)
     {
-        // Do an early return here because lowDouble() can create a lot of control flow.
-        if (!m_interpreter.needsTypeCheck(edge))
-            return;
-        
-        lowDouble(edge);
+        LValue value = lowJSValue(edge, ManualOperandSpeculation);
+        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isNotNumber(value));
     }
     
-    void speculateRealNumber(Edge edge)
+    void speculateDoubleReal(Edge edge)
     {
         // Do an early return here because lowDouble() can create a lot of control flow.
         if (!m_interpreter.needsTypeCheck(edge))
@@ -5544,19 +5508,10 @@ private:
         
         LValue value = lowDouble(edge);
         FTL_TYPE_CHECK(
-            doubleValue(value), edge, SpecFullRealNumber,
+            doubleValue(value), edge, SpecDoubleReal,
             m_out.doubleNotEqualOrUnordered(value, value));
     }
     
-    void speculateMachineInt(Edge edge)
-    {
-        if (!m_interpreter.needsTypeCheck(edge))
-            return;
-        
-        Int52Kind kind;
-        lowWhicheverInt52(edge, kind);
-    }
-    
     void speculateBoolean(Edge edge)
     {
         lowBoolean(edge);
index 5a89d6a..133ef86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,6 +71,7 @@ void reboxAccordingToFormat(
     case ValueFormatDouble: {
         jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch1);
         jit.move64ToDouble(value, FPRInfo::fpRegT0);
+        jit.sanitizeDouble(FPRInfo::fpRegT0);
         jit.boxDouble(FPRInfo::fpRegT0, value);
         jit.move64ToDouble(scratch1, FPRInfo::fpRegT0);
         break;
index a7d8011..2697092 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,6 +54,14 @@ Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock*
     return result.iterator->value;
 }
 
+void AssemblyHelpers::sanitizeDouble(FPRReg fpr)
+{
+    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
+    static const double NaN = QNaN;
+    loadDouble(&NaN, fpr);
+    notNaN.link(this);
+}
+
 #if ENABLE(SAMPLING_FLAGS)
 void AssemblyHelpers::setSamplingFlag(int32_t flag)
 {
index a6694b1..a75e5f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -417,6 +417,8 @@ public:
     void jitAssertTagsInPlace() { }
     void jitAssertArgumentCountSane() { }
 #endif
+    
+    void sanitizeDouble(FPRReg);
 
     // These methods convert between doubles, and doubles boxed and JSValues.
 #if USE(JSVALUE64)
@@ -435,6 +437,11 @@ public:
         return fpr;
     }
     
+    void boxDouble(FPRReg fpr, JSValueRegs regs)
+    {
+        boxDouble(fpr, regs.gpr());
+    }
+    
     // Here are possible arrangements of source, target, scratch:
     // - source, target, scratch can all be separate registers.
     // - source and target can be the same but scratch is separate.
@@ -467,6 +474,11 @@ public:
     {
         moveIntsToDouble(payloadGPR, tagGPR, fpr, scratchFPR);
     }
+    
+    void boxDouble(FPRReg fpr, JSValueRegs regs)
+    {
+        boxDouble(fpr, regs.tagGPR(), regs.payloadGPR());
+    }
 #endif
     
     enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };