WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
added dumping of SSA metadata
blah.patch (text/plain), 229.23 KB, created by
Filip Pizlo
on 2013-07-12 12:20:48 PDT
(
hide
)
Description:
added dumping of SSA metadata
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-07-12 12:20:48 PDT
Size:
229.23 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 152582) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,256 @@ >+2013-07-11 Filip Pizlo <fpizlo@apple.com> >+ >+ Need a short description (OOPS!). >+ Need the bug URL (OOPS!). >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * bytecode/Operands.h: >+ (JSC::Operands::fill): >+ (Operands): >+ (JSC::Operands::clear): >+ * dfg/DFGAbstractState.cpp: >+ (JSC::DFG::AbstractState::beginBasicBlock): >+ (JSC::DFG::setLiveValues): >+ (DFG): >+ (JSC::DFG::AbstractState::initialize): >+ (JSC::DFG::AbstractState::endBasicBlock): >+ (JSC::DFG::AbstractState::executeEffects): >+ (JSC::DFG::AbstractState::mergeStateAtTail): >+ (JSC::DFG::AbstractState::merge): >+ * dfg/DFGAdjacencyList.h: >+ (JSC::DFG::AdjacencyList::justOneChild): >+ (AdjacencyList): >+ * dfg/DFGBasicBlock.cpp: Added. >+ (DFG): >+ (JSC::DFG::BasicBlock::BasicBlock): >+ (JSC::DFG::BasicBlock::~BasicBlock): >+ (JSC::DFG::BasicBlock::ensureLocals): >+ (JSC::DFG::BasicBlock::isInPhis): >+ (JSC::DFG::BasicBlock::isInBlock): >+ (JSC::DFG::BasicBlock::dump): >+ (JSC::DFG::BasicBlock::SSAData::SSAData): >+ (JSC::DFG::BasicBlock::SSAData::~SSAData): >+ * dfg/DFGBasicBlock.h: >+ (BasicBlock): >+ (JSC::DFG::BasicBlock::operator[]): >+ (SSAData): >+ * dfg/DFGBasicBlockInlines.h: >+ (DFG): >+ * dfg/DFGBlockInsertionSet.cpp: Added. >+ (DFG): >+ (JSC::DFG::BlockInsertionSet::BlockInsertionSet): >+ (JSC::DFG::BlockInsertionSet::~BlockInsertionSet): >+ (JSC::DFG::BlockInsertionSet::insert): >+ (JSC::DFG::BlockInsertionSet::insertBefore): >+ (JSC::DFG::BlockInsertionSet::execute): >+ * dfg/DFGBlockInsertionSet.h: Added. >+ (DFG): >+ (BlockInsertionSet): >+ * dfg/DFGCommon.h: >+ (JSC::DFG::doesKill): >+ (DFG): >+ (JSC::DFG::killStatusForDoesKill): >+ * dfg/DFGContradictionPruningPhase.cpp: Added. >+ (DFG): >+ (ContradictionPruningPhase): >+ (JSC::DFG::ContradictionPruningPhase::ContradictionPruningPhase): >+ (JSC::DFG::ContradictionPruningPhase::run): >+ (JSC::DFG::ContradictionPruningPhase::isContradictory): >+ (JSC::DFG::ContradictionPruningPhase::makeContradictory): >+ (JSC::DFG::performContradictionPruning): >+ * dfg/DFGContradictionPruningPhase.h: Added. >+ (DFG): >+ * dfg/DFGCriticalEdgeBreakingPhase.cpp: Added. >+ (DFG): >+ (CriticalEdgeBreakingPhase): >+ (JSC::DFG::CriticalEdgeBreakingPhase::CriticalEdgeBreakingPhase): >+ (JSC::DFG::CriticalEdgeBreakingPhase::run): >+ (JSC::DFG::CriticalEdgeBreakingPhase::breakCriticalEdge): >+ (JSC::DFG::performCriticalEdgeBreaking): >+ * dfg/DFGCriticalEdgeBreakingPhase.h: Added. >+ (DFG): >+ * dfg/DFGDCEPhase.cpp: >+ (JSC::DFG::DCEPhase::run): >+ (JSC::DFG::DCEPhase::findTypeCheckRoot): >+ (JSC::DFG::DCEPhase::countNode): >+ (DCEPhase): >+ (JSC::DFG::DCEPhase::countEdge): >+ (JSC::DFG::DCEPhase::eliminateIrrelevantPhantomChildren): >+ * dfg/DFGEdge.cpp: >+ (JSC::DFG::Edge::dump): >+ * dfg/DFGEdge.h: >+ (JSC::DFG::Edge::Edge): >+ (JSC::DFG::Edge::setNode): >+ (JSC::DFG::Edge::setUseKind): >+ (JSC::DFG::Edge::setProofStatus): >+ (JSC::DFG::Edge::willNotHaveCheck): >+ (JSC::DFG::Edge::willHaveCheck): >+ (Edge): >+ (JSC::DFG::Edge::killStatusUnchecked): >+ (JSC::DFG::Edge::killStatus): >+ (JSC::DFG::Edge::setKillStatus): >+ (JSC::DFG::Edge::doesKill): >+ (JSC::DFG::Edge::doesNotKill): >+ (JSC::DFG::Edge::makeWord): >+ * dfg/DFGFlushFormat.cpp: Added. >+ (WTF): >+ (WTF::printInternal): >+ * dfg/DFGFlushFormat.h: Added. >+ (DFG): >+ (WTF): >+ * dfg/DFGFlushLivenessAnalysisPhase.cpp: Added. >+ (DFG): >+ (FlushLivenessAnalysisPhase): >+ (JSC::DFG::FlushLivenessAnalysisPhase::FlushLivenessAnalysisPhase): >+ (JSC::DFG::FlushLivenessAnalysisPhase::run): >+ (JSC::DFG::FlushLivenessAnalysisPhase::process): >+ (JSC::DFG::FlushLivenessAnalysisPhase::setForNode): >+ (JSC::DFG::FlushLivenessAnalysisPhase::flushFormat): >+ (JSC::DFG::FlushLivenessAnalysisPhase::addChildUse): >+ (JSC::DFG::performFlushLivenessAnalysis): >+ * dfg/DFGFlushLivenessAnalysisPhase.h: Added. >+ (DFG): >+ * dfg/DFGGraph.cpp: >+ (JSC::DFG::Graph::dump): >+ (JSC::DFG::Graph::dumpBlockHeader): >+ (DFG): >+ (JSC::DFG::Graph::addForDepthFirstSort): >+ (JSC::DFG::Graph::depthFirstSort): >+ * dfg/DFGGraph.h: >+ (Graph): >+ * dfg/DFGInsertionSet.h: >+ (DFG): >+ (JSC::DFG::InsertionSet::execute): >+ * dfg/DFGLivenessAnalysisPhase.cpp: Added. >+ (DFG): >+ (LivenessAnalysisPhase): >+ (JSC::DFG::LivenessAnalysisPhase::LivenessAnalysisPhase): >+ (JSC::DFG::LivenessAnalysisPhase::run): >+ (JSC::DFG::LivenessAnalysisPhase::process): >+ (JSC::DFG::LivenessAnalysisPhase::addChildUse): >+ (JSC::DFG::performLivenessAnalysis): >+ * dfg/DFGLivenessAnalysisPhase.h: Added. >+ (DFG): >+ * dfg/DFGNode.cpp: >+ (WTF::printInternal): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::hasPhi): >+ (Node): >+ (JSC::DFG::Node::phi): >+ (JSC::DFG::Node::takenBlock): >+ (JSC::DFG::Node::notTakenBlock): >+ (JSC::DFG::Node::successor): >+ * dfg/DFGNodeType.h: >+ (DFG): >+ * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: Added. >+ (DFG): >+ (OSRAvailabilityAnalysisPhase): >+ (JSC::DFG::OSRAvailabilityAnalysisPhase::OSRAvailabilityAnalysisPhase): >+ (JSC::DFG::OSRAvailabilityAnalysisPhase::run): >+ (JSC::DFG::performOSRAvailabilityAnalysis): >+ * dfg/DFGOSRAvailabilityAnalysisPhase.h: Added. >+ (DFG): >+ * dfg/DFGPlan.cpp: >+ (JSC::DFG::Plan::compileInThreadImpl): >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ (JSC::DFG::PredictionPropagationPhase::propagate): >+ * dfg/DFGSSAConversionPhase.cpp: Added. >+ (DFG): >+ (SSAConversionPhase): >+ (JSC::DFG::SSAConversionPhase::SSAConversionPhase): >+ (JSC::DFG::SSAConversionPhase::run): >+ (JSC::DFG::SSAConversionPhase::forwardPhiChildren): >+ (JSC::DFG::SSAConversionPhase::forwardPhi): >+ (JSC::DFG::SSAConversionPhase::forwardPhiEdge): >+ (JSC::DFG::SSAConversionPhase::deduplicateChildren): >+ (JSC::DFG::SSAConversionPhase::forwardNodeChildren): >+ (JSC::DFG::SSAConversionPhase::forwardNodeEdge): >+ * dfg/DFGSSAConversionPhase.h: Added. >+ (DFG): >+ * dfg/DFGVariableAccessData.h: >+ (JSC::DFG::VariableAccessData::flushFormat): >+ (VariableAccessData): >+ * ftl/FTLCapabilities.cpp: >+ (JSC::FTL::canCompile): >+ * ftl/FTLLowerDFGToLLVM.cpp: >+ (JSC::FTL::LowerDFGToLLVM::LowerDFGToLLVM): >+ (JSC::FTL::LowerDFGToLLVM::lower): >+ (JSC::FTL::LowerDFGToLLVM::createPhiVariables): >+ (JSC::FTL::LowerDFGToLLVM::checkArguments): >+ (JSC::FTL::LowerDFGToLLVM::compileBlock): >+ (JSC::FTL::LowerDFGToLLVM::compileNode): >+ (JSC::FTL::LowerDFGToLLVM::compileUpsilon): >+ (LowerDFGToLLVM): >+ (JSC::FTL::LowerDFGToLLVM::compilePhi): >+ (JSC::FTL::LowerDFGToLLVM::compileJSConstant): >+ (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant): >+ (JSC::FTL::LowerDFGToLLVM::compileGetLocal): >+ (JSC::FTL::LowerDFGToLLVM::compileSetLocal): >+ (JSC::FTL::LowerDFGToLLVM::compileAdd): >+ (JSC::FTL::LowerDFGToLLVM::compileArithSub): >+ (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::compileBitAnd): >+ (JSC::FTL::LowerDFGToLLVM::compileBitOr): >+ (JSC::FTL::LowerDFGToLLVM::compileBitXor): >+ (JSC::FTL::LowerDFGToLLVM::compileBitRShift): >+ (JSC::FTL::LowerDFGToLLVM::compileBitLShift): >+ (JSC::FTL::LowerDFGToLLVM::compileBitURShift): >+ (JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber): >+ (JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble): >+ (JSC::FTL::LowerDFGToLLVM::compileGetButterfly): >+ (JSC::FTL::LowerDFGToLLVM::compileGetArrayLength): >+ (JSC::FTL::LowerDFGToLLVM::compileGetByVal): >+ (JSC::FTL::LowerDFGToLLVM::compileGetByOffset): >+ (JSC::FTL::LowerDFGToLLVM::compileGetGlobalVar): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareEqConstant): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEqConstant): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareLess): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareLessEq): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareGreater): >+ (JSC::FTL::LowerDFGToLLVM::compileCompareGreaterEq): >+ (JSC::FTL::LowerDFGToLLVM::compileLogicalNot): >+ (JSC::FTL::LowerDFGToLLVM::lowInt32): >+ (JSC::FTL::LowerDFGToLLVM::lowCell): >+ (JSC::FTL::LowerDFGToLLVM::lowBoolean): >+ (JSC::FTL::LowerDFGToLLVM::lowDouble): >+ (JSC::FTL::LowerDFGToLLVM::lowJSValue): >+ (JSC::FTL::LowerDFGToLLVM::lowStorage): >+ (JSC::FTL::LowerDFGToLLVM::speculate): >+ (JSC::FTL::LowerDFGToLLVM::speculateBoolean): >+ (JSC::FTL::LowerDFGToLLVM::isLive): >+ (JSC::FTL::LowerDFGToLLVM::use): >+ (JSC::FTL::LowerDFGToLLVM::initializeOSRExitStateForBlock): >+ (JSC::FTL::LowerDFGToLLVM::emitOSRExitCall): >+ (JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode): >+ (JSC::FTL::LowerDFGToLLVM::setInt32): >+ (JSC::FTL::LowerDFGToLLVM::setJSValue): >+ (JSC::FTL::LowerDFGToLLVM::setBoolean): >+ (JSC::FTL::LowerDFGToLLVM::setStorage): >+ (JSC::FTL::LowerDFGToLLVM::setDouble): >+ (JSC::FTL::LowerDFGToLLVM::isValid): >+ * ftl/FTLLoweredNodeValue.h: Added. >+ (FTL): >+ (LoweredNodeValue): >+ (JSC::FTL::LoweredNodeValue::LoweredNodeValue): >+ (JSC::FTL::LoweredNodeValue::isSet): >+ (JSC::FTL::LoweredNodeValue::operator!): >+ (JSC::FTL::LoweredNodeValue::value): >+ (JSC::FTL::LoweredNodeValue::block): >+ * ftl/FTLValueFromBlock.h: >+ (JSC::FTL::ValueFromBlock::ValueFromBlock): >+ (ValueFromBlock): >+ * ftl/FTLValueSource.cpp: >+ (JSC::FTL::ValueSource::dump): >+ * ftl/FTLValueSource.h: >+ > 2013-07-11 Mark Lam <mark.lam@apple.com> > > Resurrect the CLoop LLINT on the FTL branch. >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 152582) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -170,13 +170,13 @@ > 0F46E6B9176F89DB00E1F755 /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6B7176F89D900E1F755 /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F46E6C5176F8A5E00E1F755 /* DFGLazyJSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46E6C2176F8A5B00E1F755 /* DFGLazyJSValue.cpp */; }; > 0F46E6C6176F8A6000E1F755 /* DFGLazyJSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6C3176F8A5B00E1F755 /* DFGLazyJSValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 0F46E6EF177CE95A00E1F755 /* DFGAnalysis.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6EE177CE95A00E1F755 /* DFGAnalysis.h */; }; >- 0F46E6F3177CF0D200E1F755 /* DFGNaturalLoops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46E6F1177CF0D200E1F755 /* DFGNaturalLoops.cpp */; }; >- 0F46E6F4177CF0D200E1F755 /* DFGNaturalLoops.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6F2177CF0D200E1F755 /* DFGNaturalLoops.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F46E6D9177CB90000E1F755 /* LLVMDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46E6D7177CB8FC00E1F755 /* LLVMDisassembler.cpp */; }; > 0F46E6E3177CC36600E1F755 /* LLVMDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6E0177CC36600E1F755 /* LLVMDisassembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F46E6E4177CC36600E1F755 /* UDis86Disassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6E1177CC36600E1F755 /* UDis86Disassembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F46E6E5177CC36600E1F755 /* X86Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46E6E2177CC36600E1F755 /* X86Disassembler.cpp */; }; >+ 0F46E6EF177CE95A00E1F755 /* DFGAnalysis.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6EE177CE95A00E1F755 /* DFGAnalysis.h */; }; >+ 0F46E6F3177CF0D200E1F755 /* DFGNaturalLoops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46E6F1177CF0D200E1F755 /* DFGNaturalLoops.cpp */; }; >+ 0F46E6F4177CF0D200E1F755 /* DFGNaturalLoops.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46E6F2177CF0D200E1F755 /* DFGNaturalLoops.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F493AF816D0CAD10084508B /* SourceProvider.cpp */; }; > 0F4E1A0E173AEDDC007EE2D3 /* IntendedStructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4E1A0C173AEDDC007EE2D3 /* IntendedStructureChain.cpp */; }; > 0F4E1A0F173AEDDC007EE2D3 /* IntendedStructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4E1A0D173AEDDC007EE2D3 /* IntendedStructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -353,6 +353,21 @@ > 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; }; >+ 0FE505591787AA8900B35F8C /* DFGBlockInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE505581787AA8800B35F8C /* DFGBlockInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE5055C1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE5055A1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.cpp */; }; >+ 0FE5055D1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5055B1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE50563178F5B0500B35F8C /* DFGBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50562178F5B0500B35F8C /* DFGBasicBlock.cpp */; }; >+ 0FE50571178F5B5300B35F8C /* DFGBlockInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50564178F5B5300B35F8C /* DFGBlockInsertionSet.cpp */; }; >+ 0FE50574178F5B5300B35F8C /* DFGFlushFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50567178F5B5300B35F8C /* DFGFlushFormat.cpp */; }; >+ 0FE50575178F5B5300B35F8C /* DFGFlushFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50568178F5B5300B35F8C /* DFGFlushFormat.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE50576178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE50569178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.cpp */; }; >+ 0FE50577178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5056A178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE50578178F5B5300B35F8C /* DFGLivenessAnalysisPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE5056B178F5B5300B35F8C /* DFGLivenessAnalysisPhase.cpp */; }; >+ 0FE50579178F5B5300B35F8C /* DFGLivenessAnalysisPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5056C178F5B5300B35F8C /* DFGLivenessAnalysisPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE5057A178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE5056D178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.cpp */; }; >+ 0FE5057B178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5056E178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FE5057C178F5B5300B35F8C /* DFGSSAConversionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE5056F178F5B5300B35F8C /* DFGSSAConversionPhase.cpp */; }; >+ 0FE5057D178F5B5300B35F8C /* DFGSSAConversionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE50570178F5B5300B35F8C /* DFGSSAConversionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */; }; > 0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -1186,13 +1201,13 @@ > 0F46E6B7176F89D900E1F755 /* FTLSwitchCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSwitchCase.h; path = ftl/FTLSwitchCase.h; sourceTree = "<group>"; }; > 0F46E6C2176F8A5B00E1F755 /* DFGLazyJSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyJSValue.cpp; path = dfg/DFGLazyJSValue.cpp; sourceTree = "<group>"; }; > 0F46E6C3176F8A5B00E1F755 /* DFGLazyJSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyJSValue.h; path = dfg/DFGLazyJSValue.h; sourceTree = "<group>"; }; >- 0F46E6EE177CE95A00E1F755 /* DFGAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAnalysis.h; path = dfg/DFGAnalysis.h; sourceTree = "<group>"; }; >- 0F46E6F1177CF0D200E1F755 /* DFGNaturalLoops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNaturalLoops.cpp; path = dfg/DFGNaturalLoops.cpp; sourceTree = "<group>"; }; >- 0F46E6F2177CF0D200E1F755 /* DFGNaturalLoops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNaturalLoops.h; path = dfg/DFGNaturalLoops.h; sourceTree = "<group>"; }; > 0F46E6D7177CB8FC00E1F755 /* LLVMDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMDisassembler.cpp; path = disassembler/LLVMDisassembler.cpp; sourceTree = "<group>"; }; > 0F46E6E0177CC36600E1F755 /* LLVMDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLVMDisassembler.h; path = disassembler/LLVMDisassembler.h; sourceTree = "<group>"; }; > 0F46E6E1177CC36600E1F755 /* UDis86Disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UDis86Disassembler.h; path = disassembler/UDis86Disassembler.h; sourceTree = "<group>"; }; > 0F46E6E2177CC36600E1F755 /* X86Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = X86Disassembler.cpp; path = disassembler/X86Disassembler.cpp; sourceTree = "<group>"; }; >+ 0F46E6EE177CE95A00E1F755 /* DFGAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAnalysis.h; path = dfg/DFGAnalysis.h; sourceTree = "<group>"; }; >+ 0F46E6F1177CF0D200E1F755 /* DFGNaturalLoops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNaturalLoops.cpp; path = dfg/DFGNaturalLoops.cpp; sourceTree = "<group>"; }; >+ 0F46E6F2177CF0D200E1F755 /* DFGNaturalLoops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNaturalLoops.h; path = dfg/DFGNaturalLoops.h; sourceTree = "<group>"; }; > 0F493AF816D0CAD10084508B /* SourceProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProvider.cpp; sourceTree = "<group>"; }; > 0F4E1A0C173AEDDC007EE2D3 /* IntendedStructureChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntendedStructureChain.cpp; sourceTree = "<group>"; }; > 0F4E1A0D173AEDDC007EE2D3 /* IntendedStructureChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntendedStructureChain.h; sourceTree = "<group>"; }; >@@ -1384,6 +1399,21 @@ > 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; }; > 0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; }; > 0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; }; >+ 0FE505581787AA8800B35F8C /* DFGBlockInsertionSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DFGBlockInsertionSet.h; path = dfg/DFGBlockInsertionSet.h; sourceTree = "<group>"; }; >+ 0FE5055A1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCriticalEdgeBreakingPhase.cpp; path = dfg/DFGCriticalEdgeBreakingPhase.cpp; sourceTree = "<group>"; }; >+ 0FE5055B1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCriticalEdgeBreakingPhase.h; path = dfg/DFGCriticalEdgeBreakingPhase.h; sourceTree = "<group>"; }; >+ 0FE50562178F5B0500B35F8C /* DFGBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBasicBlock.cpp; path = dfg/DFGBasicBlock.cpp; sourceTree = "<group>"; }; >+ 0FE50564178F5B5300B35F8C /* DFGBlockInsertionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBlockInsertionSet.cpp; path = dfg/DFGBlockInsertionSet.cpp; sourceTree = "<group>"; }; >+ 0FE50567178F5B5300B35F8C /* DFGFlushFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFlushFormat.cpp; path = dfg/DFGFlushFormat.cpp; sourceTree = "<group>"; }; >+ 0FE50568178F5B5300B35F8C /* DFGFlushFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlushFormat.h; path = dfg/DFGFlushFormat.h; sourceTree = "<group>"; }; >+ 0FE50569178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFlushLivenessAnalysisPhase.cpp; path = dfg/DFGFlushLivenessAnalysisPhase.cpp; sourceTree = "<group>"; }; >+ 0FE5056A178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlushLivenessAnalysisPhase.h; path = dfg/DFGFlushLivenessAnalysisPhase.h; sourceTree = "<group>"; }; >+ 0FE5056B178F5B5300B35F8C /* DFGLivenessAnalysisPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLivenessAnalysisPhase.cpp; path = dfg/DFGLivenessAnalysisPhase.cpp; sourceTree = "<group>"; }; >+ 0FE5056C178F5B5300B35F8C /* DFGLivenessAnalysisPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLivenessAnalysisPhase.h; path = dfg/DFGLivenessAnalysisPhase.h; sourceTree = "<group>"; }; >+ 0FE5056D178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRAvailabilityAnalysisPhase.cpp; path = dfg/DFGOSRAvailabilityAnalysisPhase.cpp; sourceTree = "<group>"; }; >+ 0FE5056E178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRAvailabilityAnalysisPhase.h; path = dfg/DFGOSRAvailabilityAnalysisPhase.h; sourceTree = "<group>"; }; >+ 0FE5056F178F5B5300B35F8C /* DFGSSAConversionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSSAConversionPhase.cpp; path = dfg/DFGSSAConversionPhase.cpp; sourceTree = "<group>"; }; >+ 0FE50570178F5B5300B35F8C /* DFGSSAConversionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSSAConversionPhase.h; path = dfg/DFGSSAConversionPhase.h; sourceTree = "<group>"; }; > 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredWatchpoints.cpp; path = dfg/DFGDesiredWatchpoints.cpp; sourceTree = "<group>"; }; > 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredWatchpoints.h; path = dfg/DFGDesiredWatchpoints.h; sourceTree = "<group>"; }; > 0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviations.h; path = ftl/FTLAbbreviations.h; sourceTree = "<group>"; }; >@@ -2962,10 +2992,13 @@ > 0FC0976C1468AB4A00CF2442 /* DFGAssemblyHelpers.h */, > 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */, > 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */, >+ 0FE50562178F5B0500B35F8C /* DFGBasicBlock.cpp */, > 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */, > 0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */, > 0FD2812517793BE300BBB0F3 /* DFGBinarySwitch.cpp */, > 0FD2812617793BE300BBB0F3 /* DFGBinarySwitch.h */, >+ 0FE50564178F5B5300B35F8C /* DFGBlockInsertionSet.cpp */, >+ 0FE505581787AA8800B35F8C /* DFGBlockInsertionSet.h */, > 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */, > 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */, > 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */, >@@ -2985,6 +3018,8 @@ > 0F3B3A18153E68EF003ED0FF /* DFGConstantFoldingPhase.h */, > 0FBE0F6B16C1DB010082C5E8 /* DFGCPSRethreadingPhase.cpp */, > 0FBE0F6C16C1DB010082C5E8 /* DFGCPSRethreadingPhase.h */, >+ 0FE5055A1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.cpp */, >+ 0FE5055B1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.h */, > 0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */, > 0FFFC94E14EF909500C72532 /* DFGCSEPhase.h */, > 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */, >@@ -3011,6 +3046,10 @@ > 0FDB2CD41742D804007B3C1B /* DFGFinalizer.h */, > 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */, > 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */, >+ 0FE50567178F5B5300B35F8C /* DFGFlushFormat.cpp */, >+ 0FE50568178F5B5300B35F8C /* DFGFlushFormat.h */, >+ 0FE50569178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.cpp */, >+ 0FE5056A178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.h */, > 86AE6C4B136A11E400963012 /* DFGFPRInfo.h */, > 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */, > 86AE6C4C136A11E400963012 /* DFGGPRInfo.h */, >@@ -3025,6 +3064,8 @@ > 0FDB2CD61742D804007B3C1B /* DFGJITFinalizer.h */, > 0F46E6C2176F8A5B00E1F755 /* DFGLazyJSValue.cpp */, > 0F46E6C3176F8A5B00E1F755 /* DFGLazyJSValue.h */, >+ 0FE5056B178F5B5300B35F8C /* DFGLivenessAnalysisPhase.cpp */, >+ 0FE5056C178F5B5300B35F8C /* DFGLivenessAnalysisPhase.h */, > 0FB4B51C16B62772003F696B /* DFGLongLivedState.cpp */, > 0FB4B51D16B62772003F696B /* DFGLongLivedState.h */, > 0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */, >@@ -3041,6 +3082,8 @@ > 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */, > 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */, > 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */, >+ 0FE5056D178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.cpp */, >+ 0FE5056E178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.h */, > 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */, > 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */, > 0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */, >@@ -3078,6 +3121,8 @@ > 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */, > 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */, > 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */, >+ 0FE5056F178F5B5300B35F8C /* DFGSSAConversionPhase.cpp */, >+ 0FE50570178F5B5300B35F8C /* DFGSSAConversionPhase.h */, > 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */, > 0FC0979F146B28C700CF2442 /* DFGThunks.cpp */, > 0FC097A0146B28C700CF2442 /* DFGThunks.h */, >@@ -3298,6 +3343,7 @@ > 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */, > 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */, > BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */, >+ 0FE50579178F5B5300B35F8C /* DFGLivenessAnalysisPhase.h in Headers */, > 865F408810E7D56300947361 /* APIShims.h in Headers */, > BCF605140E203EF800B9A64D /* ArgList.h in Headers */, > BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */, >@@ -3407,6 +3453,7 @@ > 0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */, > 0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */, > 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */, >+ 0FE5057D178F5B5300B35F8C /* DFGSSAConversionPhase.h in Headers */, > 0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */, > 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */, > 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */, >@@ -3428,6 +3475,7 @@ > 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */, > 0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */, > 0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */, >+ 0FE50577178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.h in Headers */, > 0F4E1A12173AF07B007EE2D3 /* DFGDesiredStructureChains.h in Headers */, > 0FFFC95C14EF90AF00C72532 /* DFGPhase.h in Headers */, > 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */, >@@ -3444,6 +3492,7 @@ > 0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */, > 0F2BDC471522802500CD8910 /* DFGValueRecoveryOverride.h in Headers */, > FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */, >+ 0FE5055D1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.h in Headers */, > 0F2BDC481522802900CD8910 /* DFGValueSource.h in Headers */, > 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */, > 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */, >@@ -3591,6 +3640,8 @@ > 0F766D3515AE253B008F363E /* JumpReplacementWatchpoint.h in Headers */, > 0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */, > BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */, >+ 0FE50575178F5B5300B35F8C /* DFGFlushFormat.h in Headers */, >+ 0FE505591787AA8900B35F8C /* DFGBlockInsertionSet.h in Headers */, > A72FFD64139985A800E5365A /* KeywordLookup.h in Headers */, > 969A072A0ED1CE6900F1F681 /* Label.h in Headers */, > 960097A60EBABB58007A7297 /* LabelScope.h in Headers */, >@@ -3708,6 +3759,7 @@ > 1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */, > 0FDB2CDE1742D804007B3C1B /* DFGJITFinalizer.h in Headers */, > 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */, >+ 0FE5057B178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.h in Headers */, > 0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */, > 0F235BDB17178E1C00690C7F /* FTLExitValue.h in Headers */, > 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */, >@@ -4194,6 +4246,7 @@ > 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */, > 0FDB2CD91742D804007B3C1B /* DFGFailedFinalizer.cpp in Sources */, > 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */, >+ 0FE50578178F5B5300B35F8C /* DFGLivenessAnalysisPhase.cpp in Sources */, > 0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */, > 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, > 0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */, >@@ -4225,9 +4278,11 @@ > 0FC0976E1468AB5100CF2442 /* DFGAssemblyHelpers.cpp in Sources */, > 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */, > 0F235BD817178E1C00690C7F /* FTLExitThunkGenerator.cpp in Sources */, >+ 0FE50574178F5B5300B35F8C /* DFGFlushFormat.cpp in Sources */, > 0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */, > 0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */, > 0F3B3A271544C995003ED0FF /* DFGCFGSimplificationPhase.cpp in Sources */, >+ 0FE50571178F5B5300B35F8C /* DFGBlockInsertionSet.cpp in Sources */, > 0F235BD117178E1C00690C7F /* FTLCArgumentGetter.cpp in Sources */, > 0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */, > 0FF0F19D16B72A08005DF95B /* DFGCommon.cpp in Sources */, >@@ -4346,6 +4401,7 @@ > 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */, > 978801401471AD920041B016 /* JSDateMath.cpp in Sources */, > 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */, >+ 0FE50576178F5B5300B35F8C /* DFGFlushLivenessAnalysisPhase.cpp in Sources */, > E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */, > 147F39D2107EC37600427A48 /* JSGlobalObject.cpp in Sources */, > 14E9D17B107EC469004DDA21 /* JSGlobalObjectFunctions.cpp in Sources */, >@@ -4383,6 +4439,7 @@ > BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */, > 0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */, > 95AB83420DA4322500BC83F3 /* LegacyProfiler.cpp in Sources */, >+ 0FE5057C178F5B5300B35F8C /* DFGSSAConversionPhase.cpp in Sources */, > 148F21B0107EC5410042EC2C /* Lexer.cpp in Sources */, > 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */, > A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */, >@@ -4405,7 +4462,9 @@ > 14D2F3DA139F4BE200491031 /* MarkedSpace.cpp in Sources */, > 142D6F1113539A4100B02E86 /* MarkStack.cpp in Sources */, > 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */, >+ 0FE5057A178F5B5300B35F8C /* DFGOSRAvailabilityAnalysisPhase.cpp in Sources */, > 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */, >+ 0FE5055C1787B0CF00B35F8C /* DFGCriticalEdgeBreakingPhase.cpp in Sources */, > 0FD2812717793BE500BBB0F3 /* DFGBinarySwitch.cpp in Sources */, > 0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */, > 86EBF2FF1560F06A008E9222 /* NameConstructor.cpp in Sources */, >@@ -4417,6 +4476,7 @@ > 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */, > 14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */, > 14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */, >+ 0FE50563178F5B0500B35F8C /* DFGBasicBlock.cpp in Sources */, > 14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */, > 86F3EEBE168CDE930077B92A /* ObjCCallbackFunction.mm in Sources */, > 14469DE5107EC7E700650446 /* ObjectConstructor.cpp in Sources */, >Index: Source/JavaScriptCore/bytecode/Operands.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Operands.h (revision 152582) >+++ Source/JavaScriptCore/bytecode/Operands.h (working copy) >@@ -43,7 +43,7 @@ template<typename T> struct OperandValue > template<typename T> > struct OperandValueTraits { > static T defaultValue() { return T(); } >- static void dump(const T& value, PrintStream& out) { value.dump(out); } >+ static void dump(const T& value, PrintStream& out) { out.print(value); } > }; > > enum OperandKind { ArgumentOperand, LocalOperand }; >@@ -209,12 +209,25 @@ public: > setLocalFirstTime(operand, value); > } > >- void clear() >+ void fill(T value) > { > for (size_t i = 0; i < m_arguments.size(); ++i) >- m_arguments[i] = Traits::defaultValue(); >+ m_arguments[i] = value; > for (size_t i = 0; i < m_locals.size(); ++i) >- m_locals[i] = Traits::defaultValue(); >+ m_locals[i] = value; >+ } >+ >+ void clear() >+ { >+ fill(Traits::defaultValue()); >+ } >+ >+ bool operator==(const Operands& other) const >+ { >+ ASSERT(numberOfArguments() == other.numberOfArguments()); >+ ASSERT(numberOfLocals() == other.numberOfLocals()); >+ >+ return m_arguments == other.m_arguments && m_locals == other.m_locals; > } > > void dump(PrintStream& out) const; >Index: Source/JavaScriptCore/dfg/DFGAbstractState.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractState.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGAbstractState.cpp (working copy) >@@ -74,6 +74,16 @@ void AbstractState::beginBasicBlock(Basi > } > } > >+ if (m_graph.m_form == SSA) { >+ HashMap<Node*, AbstractValue>::iterator iter = basicBlock->ssa->valuesAtHead.begin(); >+ HashMap<Node*, AbstractValue>::iterator end = basicBlock->ssa->valuesAtHead.end(); >+ for (; iter != end; ++iter) { >+ forNode(iter->key) = iter->value; >+ if (iter->value.hasClobberableState()) >+ m_haveStructures = true; >+ } >+ } >+ > basicBlock->cfaShouldRevisit = false; > basicBlock->cfaHasVisited = true; > m_block = basicBlock; >@@ -83,9 +93,19 @@ void AbstractState::beginBasicBlock(Basi > m_currentNode = 0; > } > >-void AbstractState::initialize(Graph& graph) >+static void setLiveValues(HashMap<Node*, AbstractValue>& values, HashSet<Node*>& live) >+{ >+ values.clear(); >+ >+ HashSet<Node*>::iterator iter = live.begin(); >+ HashSet<Node*>::iterator end = live.end(); >+ for (; iter != end; ++iter) >+ values.add(*iter, AbstractValue()); >+} >+ >+void AbstractState::initialize() > { >- BasicBlock* root = graph.block(0); >+ BasicBlock* root = m_graph.block(0); > root->cfaShouldRevisit = true; > root->cfaHasVisited = false; > root->cfaFoundConstants = false; >@@ -118,8 +138,8 @@ void AbstractState::initialize(Graph& gr > root->valuesAtHead.local(i).clear(); > root->valuesAtTail.local(i).clear(); > } >- for (BlockIndex blockIndex = 1 ; blockIndex < graph.numBlocks(); ++blockIndex) { >- BasicBlock* block = graph.block(blockIndex); >+ for (BlockIndex blockIndex = 1 ; blockIndex < m_graph.numBlocks(); ++blockIndex) { >+ BasicBlock* block = m_graph.block(blockIndex); > if (!block) > continue; > if (!block->isReachable) >@@ -137,12 +157,12 @@ void AbstractState::initialize(Graph& gr > } > if (!block->isOSRTarget) > continue; >- if (block->bytecodeBegin != graph.m_plan.osrEntryBytecodeIndex) >+ if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex) > continue; >- for (size_t i = 0; i < graph.m_plan.mustHandleValues.size(); ++i) { >+ for (size_t i = 0; i < m_graph.m_plan.mustHandleValues.size(); ++i) { > AbstractValue value; >- value.setMostSpecific(graph, graph.m_plan.mustHandleValues[i]); >- int operand = graph.m_plan.mustHandleValues.operandForIndex(i); >+ value.setMostSpecific(m_graph, m_graph.m_plan.mustHandleValues[i]); >+ int operand = m_graph.m_plan.mustHandleValues.operandForIndex(i); > block->valuesAtHead.operand(operand).merge(value); > #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) > dataLogF(" Initializing Block #%u, operand r%d, to ", blockIndex, operand); >@@ -151,6 +171,10 @@ void AbstractState::initialize(Graph& gr > #endif > } > block->cfaShouldRevisit = true; >+ if (m_graph.m_form == SSA) { >+ setLiveValues(block->ssa->valuesAtHead, block->ssa->liveAtHead); >+ setLiveValues(block->ssa->valuesAtTail, block->ssa->liveAtTail); >+ } > } > } > >@@ -172,20 +196,41 @@ bool AbstractState::endBasicBlock(MergeM > bool changed = false; > > if (mergeMode != DontMerge || !ASSERT_DISABLED) { >- for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { >+ switch (m_graph.m_form) { >+ case ThreadedCPS: { >+ for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { > #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) >- dataLogF(" Merging state for argument %zu.\n", argument); >+ dataLogF(" Merging state for argument %zu.\n", argument); > #endif >- AbstractValue& destination = block->valuesAtTail.argument(argument); >- changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); >- } >- >- for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { >+ AbstractValue& destination = block->valuesAtTail.argument(argument); >+ changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); >+ } >+ >+ for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { > #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) >- dataLogF(" Merging state for local %zu.\n", local); >+ dataLogF(" Merging state for local %zu.\n", local); > #endif >- AbstractValue& destination = block->valuesAtTail.local(local); >- changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); >+ AbstractValue& destination = block->valuesAtTail.local(local); >+ changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); >+ } >+ break; >+ } >+ >+ case SSA: { >+ for (size_t i = 0; i < block->valuesAtTail.size(); ++i) >+ changed |= block->valuesAtTail[i].merge(m_variables[i]); >+ >+ HashSet<Node*>::iterator iter = block->ssa->liveAtTail.begin(); >+ HashSet<Node*>::iterator end = block->ssa->liveAtTail.end(); >+ for (; iter != end; ++iter) { >+ Node* node = *iter; >+ changed |= block->ssa->valuesAtTail.find(node)->value.merge(forNode(node)); >+ } >+ break; >+ } >+ >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); > } > } > >@@ -323,13 +368,13 @@ bool AbstractState::executeEffects(unsig > break; > } > >+ case MovHint: > case MovHintAndCheck: { > // Don't need to do anything. A MovHint is effectively a promise that the SetLocal > // was dead. > break; > } > >- case MovHint: > case ZombieHint: { > RELEASE_ASSERT_NOT_REACHED(); > break; >@@ -1586,6 +1631,17 @@ bool AbstractState::executeEffects(unsig > break; > > case Phi: >+ RELEASE_ASSERT(m_graph.m_form == SSA); >+ // The state of this node would have already been decided. >+ break; >+ >+ case Upsilon: { >+ AbstractValue& value = forNode(node->child1()); >+ forNode(node) = value; >+ forNode(node->phi()) = value; >+ break; >+ } >+ > case Flush: > case PhantomLocal: > case Breakpoint: >@@ -1678,7 +1734,7 @@ inline void AbstractState::clobberStruct > m_didClobber = true; > } > >-inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node) >+bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node) > { > if (!node) > return false; >@@ -1766,21 +1822,44 @@ inline bool AbstractState::mergeStateAtT > return true; > } > >-inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to) >+bool AbstractState::merge(BasicBlock* from, BasicBlock* to) > { > ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments()); > ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals()); > > bool changed = false; > >- for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) { >- AbstractValue& destination = to->valuesAtHead.argument(argument); >- changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument)); >+ switch (m_graph.m_form) { >+ case ThreadedCPS: { >+ for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) { >+ AbstractValue& destination = to->valuesAtHead.argument(argument); >+ changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument)); >+ } >+ >+ for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) { >+ AbstractValue& destination = to->valuesAtHead.local(local); >+ changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local)); >+ } >+ break; > } >- >- for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) { >- AbstractValue& destination = to->valuesAtHead.local(local); >- changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local)); >+ >+ case SSA: { >+ for (size_t i = from->valuesAtTail.size(); i--;) >+ changed |= to->valuesAtHead[i].merge(from->valuesAtTail[i]); >+ >+ HashSet<Node*>::iterator iter = to->ssa->liveAtHead.begin(); >+ HashSet<Node*>::iterator end = to->ssa->liveAtHead.end(); >+ for (; iter != end; ++iter) { >+ Node* node = *iter; >+ changed |= to->ssa->valuesAtHead.find(node)->value.merge( >+ from->ssa->valuesAtTail.find(node)->value); >+ } >+ break; >+ } >+ >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; > } > > if (!to->cfaHasVisited) >Index: Source/JavaScriptCore/dfg/DFGAbstractState.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractState.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGAbstractState.h (working copy) >@@ -130,7 +130,7 @@ public: > // Call this before beginning CFA to initialize the abstract values of > // arguments, and to indicate which blocks should be listed for CFA > // execution. >- static void initialize(Graph&); >+ void initialize(); > > // Start abstractly executing the given basic block. Initializes the > // notion of abstract state to what we believe it to be at the head >Index: Source/JavaScriptCore/dfg/DFGAdjacencyList.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAdjacencyList.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGAdjacencyList.h (working copy) >@@ -99,6 +99,15 @@ public: > > Edge child1Unchecked() const { return m_words[0]; } > >+ Edge justOneChild() const >+ { >+ if (!!child1() && !child2()) { >+ ASSERT(!child3()); >+ return child1(); >+ } >+ return Edge(); >+ } >+ > void initialize(Edge child1, Edge child2, Edge child3) > { > child(0) = child1; >Index: Source/JavaScriptCore/dfg/DFGBasicBlock.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBasicBlock.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGBasicBlock.cpp (working copy) >@@ -0,0 +1,101 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGBasicBlock.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "Operations.h" >+ >+namespace JSC { namespace DFG { >+ >+BasicBlock::BasicBlock(unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals) >+ : bytecodeBegin(bytecodeBegin) >+ , index(NoBlock) >+ , isOSRTarget(false) >+ , cfaHasVisited(false) >+ , cfaShouldRevisit(false) >+ , cfaFoundConstants(false) >+ , cfaDidFinish(true) >+ , cfaBranchDirection(InvalidBranchDirection) >+#if !ASSERT_DISABLED >+ , isLinked(false) >+#endif >+ , isReachable(false) >+ , variablesAtHead(numArguments, numLocals) >+ , variablesAtTail(numArguments, numLocals) >+ , valuesAtHead(numArguments, numLocals) >+ , valuesAtTail(numArguments, numLocals) >+{ >+} >+ >+BasicBlock::~BasicBlock() { } >+ >+void BasicBlock::ensureLocals(unsigned newNumLocals) >+{ >+ variablesAtHead.ensureLocals(newNumLocals); >+ variablesAtTail.ensureLocals(newNumLocals); >+ valuesAtHead.ensureLocals(newNumLocals); >+ valuesAtTail.ensureLocals(newNumLocals); >+} >+ >+bool BasicBlock::isInPhis(Node* node) const >+{ >+ for (size_t i = 0; i < phis.size(); ++i) { >+ if (phis[i] == node) >+ return true; >+ } >+ return false; >+} >+ >+bool BasicBlock::isInBlock(Node* myNode) const >+{ >+ for (size_t i = 0; i < numNodes(); ++i) { >+ if (node(i) == myNode) >+ return true; >+ } >+ return false; >+} >+ >+void BasicBlock::dump(PrintStream& out) const >+{ >+ out.print("#", index); >+} >+ >+BasicBlock::SSAData::SSAData(BasicBlock* block) >+ : flushFormatAtHead(OperandsLike, block->variablesAtHead) >+ , flushFormatAtTail(OperandsLike, block->variablesAtHead) >+ , availabilityAtHead(OperandsLike, block->variablesAtHead) >+ , availabilityAtTail(OperandsLike, block->variablesAtHead) >+{ >+} >+ >+BasicBlock::SSAData::~SSAData() { } >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGBasicBlock.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBasicBlock.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGBasicBlock.h (working copy) >@@ -33,6 +33,8 @@ > #include "DFGNode.h" > #include "DFGVariadicFunction.h" > #include "Operands.h" >+#include <wtf/HashMap.h> >+#include <wtf/HashSet.h> > #include <wtf/OwnPtr.h> > #include <wtf/Vector.h> > >@@ -44,42 +46,16 @@ class InsertionSet; > typedef Vector<BasicBlock*, 2> PredecessorList; > > struct BasicBlock : RefCounted<BasicBlock> { >- BasicBlock(unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals) >- : bytecodeBegin(bytecodeBegin) >- , index(NoBlock) >- , isOSRTarget(false) >- , cfaHasVisited(false) >- , cfaShouldRevisit(false) >- , cfaFoundConstants(false) >- , cfaDidFinish(true) >- , cfaBranchDirection(InvalidBranchDirection) >-#if !ASSERT_DISABLED >- , isLinked(false) >-#endif >- , isReachable(false) >- , variablesAtHead(numArguments, numLocals) >- , variablesAtTail(numArguments, numLocals) >- , valuesAtHead(numArguments, numLocals) >- , valuesAtTail(numArguments, numLocals) >- { >- } >+ BasicBlock(unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals); >+ ~BasicBlock(); > >- ~BasicBlock() >- { >- } >- >- void ensureLocals(unsigned newNumLocals) >- { >- variablesAtHead.ensureLocals(newNumLocals); >- variablesAtTail.ensureLocals(newNumLocals); >- valuesAtHead.ensureLocals(newNumLocals); >- valuesAtTail.ensureLocals(newNumLocals); >- } >+ void ensureLocals(unsigned newNumLocals); > > size_t size() const { return m_nodes.size(); } > bool isEmpty() const { return !size(); } > Node*& at(size_t i) { return m_nodes[i]; } > Node* at(size_t i) const { return m_nodes[i]; } >+ Node*& operator[](size_t i) { return at(i); } > Node* operator[](size_t i) const { return at(i); } > Node* last() const { return at(size() - 1); } > void resize(size_t size) { m_nodes.resize(size); } >@@ -96,31 +72,16 @@ struct BasicBlock : RefCounted<BasicBloc > } > bool isPhiIndex(size_t i) const { return i < phis.size(); } > >- bool isInPhis(Node* node) const >- { >- for (size_t i = 0; i < phis.size(); ++i) { >- if (phis[i] == node) >- return true; >- } >- return false; >- } >- >- bool isInBlock(Node* myNode) const >- { >- for (size_t i = 0; i < numNodes(); ++i) { >- if (node(i) == myNode) >- return true; >- } >- return false; >- } >+ bool isInPhis(Node* node) const; >+ bool isInBlock(Node* myNode) const; > > unsigned numSuccessors() { return last()->numSuccessors(); } > >- BasicBlock* successor(unsigned index) >+ BasicBlock*& successor(unsigned index) > { > return last()->successor(index); > } >- BasicBlock* successorForCondition(bool condition) >+ BasicBlock*& successorForCondition(bool condition) > { > return last()->successorForCondition(condition); > } >@@ -130,10 +91,12 @@ struct BasicBlock : RefCounted<BasicBloc > DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) > #undef DFG_DEFINE_APPEND_NODE > >- void dump(PrintStream& out) const >- { >- out.print("#", index); >- } >+#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 >+ >+ void dump(PrintStream& out) const; > > // This value is used internally for block linking and OSR entry. It is mostly meaningless > // for other purposes due to inlining. >@@ -160,6 +123,21 @@ struct BasicBlock : RefCounted<BasicBloc > > Operands<AbstractValue> valuesAtHead; > Operands<AbstractValue> valuesAtTail; >+ >+ struct SSAData { >+ Operands<FlushFormat> flushFormatAtHead; >+ Operands<FlushFormat> flushFormatAtTail; >+ Operands<Node*> availabilityAtHead; >+ Operands<Node*> availabilityAtTail; >+ HashSet<Node*> liveAtHead; >+ HashSet<Node*> liveAtTail; >+ HashMap<Node*, AbstractValue> valuesAtHead; >+ HashMap<Node*, AbstractValue> valuesAtTail; >+ >+ SSAData(BasicBlock*); >+ ~SSAData(); >+ }; >+ OwnPtr<SSAData> ssa; > > private: > friend class InsertionSet; >Index: Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h (working copy) >@@ -43,6 +43,17 @@ namespace JSC { namespace DFG { > 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); \ >+ append(last()); \ >+ at(size() - 2) = result; \ >+ return result; \ >+ } >+ DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) >+#undef DFG_DEFINE_APPEND_NODE >+ > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGBlockInsertionSet.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBlockInsertionSet.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGBlockInsertionSet.cpp (working copy) >@@ -0,0 +1,100 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGBlockInsertionSet.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+BlockInsertionSet::BlockInsertionSet(Graph& graph) >+ : m_graph(graph) >+{ >+} >+ >+BlockInsertionSet::~BlockInsertionSet() { } >+ >+void BlockInsertionSet::insert(const BlockInsertion& insertion) >+{ >+ m_insertions.append(insertion); >+} >+ >+void BlockInsertionSet::insert(size_t index, PassRefPtr<BasicBlock> block) >+{ >+ insert(BlockInsertion(index, block)); >+} >+ >+BasicBlock* BlockInsertionSet::insert(size_t index) >+{ >+ RefPtr<BasicBlock> block = adoptRef(new BasicBlock( >+ UINT_MAX, >+ m_graph.block(0)->variablesAtHead.numberOfArguments(), >+ m_graph.block(0)->variablesAtHead.numberOfLocals())); >+ insert(index, block); >+ return block.get(); >+} >+ >+BasicBlock* BlockInsertionSet::insertBefore(BasicBlock* before) >+{ >+ return insert(before->index); >+} >+ >+bool BlockInsertionSet::execute() >+{ >+ if (m_insertions.isEmpty()) >+ return false; >+ >+ // We allow insertions to be given to us in any order. So, we need to >+ // sort them before running WTF::executeInsertions. >+ std::sort(m_insertions.begin(), m_insertions.end()); >+ >+ executeInsertions(m_graph.m_blocks, m_insertions); >+ >+ // Prune out empty entries. This isn't strictly necessary but it's >+ // healthy to keep the block list from growing. >+ unsigned targetIndex = 0; >+ for (unsigned sourceIndex = 0; sourceIndex < m_graph.m_blocks.size();) { >+ RefPtr<BasicBlock> block = m_graph.m_blocks[sourceIndex++]; >+ if (!block) >+ continue; >+ m_graph.m_blocks[targetIndex++] = block; >+ } >+ m_graph.m_blocks.resize(targetIndex); >+ >+ // Make sure that the blocks know their new indices. >+ for (unsigned i = 0; i < m_graph.m_blocks.size(); ++i) >+ m_graph.m_blocks[i]->index = i; >+ >+ // And finally, invalidate all analyses that rely on the CFG. >+ m_graph.invalidateCFG(); >+ >+ return true; >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGBlockInsertionSet.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBlockInsertionSet.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGBlockInsertionSet.h (working copy) >@@ -0,0 +1,63 @@ >+/* >+ * 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 DFGBlockInsertionSet_h >+#define DFGBlockInsertionSet_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGGraph.h" >+#include <wtf/Insertion.h> >+#include <wtf/Vector.h> >+ >+namespace JSC { namespace DFG { >+ >+typedef WTF::Insertion<RefPtr<BasicBlock> > BlockInsertion; >+ >+class BlockInsertionSet { >+public: >+ BlockInsertionSet(Graph& graph); >+ ~BlockInsertionSet(); >+ >+ void insert(const BlockInsertion& insertion); >+ void insert(size_t index, PassRefPtr<BasicBlock> block); >+ BasicBlock* insert(size_t index); >+ BasicBlock* insertBefore(BasicBlock* before); >+ >+ bool execute(); >+ >+private: >+ Graph& m_graph; >+ Vector<BlockInsertion, 8> m_insertions; >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGBlockInsertionSet_h >+ >Index: Source/JavaScriptCore/dfg/DFGCFAPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (working copy) >@@ -68,7 +68,7 @@ public: > // after all predecessors have been visited. Only loops will cause this analysis to > // revisit blocks, and the amount of revisiting is proportional to loop depth. > >- AbstractState::initialize(m_graph); >+ m_state.initialize(); > > do { > m_changed = false; >Index: Source/JavaScriptCore/dfg/DFGCommon.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCommon.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGCommon.h (working copy) >@@ -212,7 +212,10 @@ enum GraphForm { > // > // ThreadedCPS form is suitable for data flow analysis (CFA, prediction > // propagation), register allocation, and code generation. >- ThreadedCPS >+ ThreadedCPS, >+ >+ // SSA form. See DFGSSAConversionPhase.h for a description. >+ SSA > }; > > // Describes the state of the UnionFind structure of VariableAccessData's. >@@ -250,6 +253,19 @@ inline ProofStatus proofStatusForIsProve > return isProved ? IsProved : NeedsCheck; > } > >+enum KillStatus { DoesNotKill, DoesKill }; >+ >+inline bool doesKill(KillStatus killStatus) >+{ >+ ASSERT(killStatus == DoesNotKill || killStatus == DoesKill); >+ return killStatus == DoesKill; >+} >+ >+inline KillStatus killStatusForDoesKill(bool doesKill) >+{ >+ return doesKill ? DoesKill : DoesNotKill; >+} >+ > template<typename T, typename U> > bool checkAndSet(T& left, U right) > { >Index: Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.cpp (working copy) >@@ -0,0 +1,98 @@ >+/* >+ * Copyright (C) 2012, 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. >+ */ >+ >+#include "config.h" >+#include "DFGCriticalEdgeBreakingPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGBasicBlockInlines.h" >+#include "DFGBlockInsertionSet.h" >+#include "DFGGraph.h" >+#include "DFGPhase.h" >+#include "Operations.h" >+#include <wtf/HashMap.h> >+ >+namespace JSC { namespace DFG { >+ >+class CriticalEdgeBreakingPhase : public Phase { >+public: >+ CriticalEdgeBreakingPhase(Graph& graph) >+ : Phase(graph, "critical edge breaking") >+ , m_insertionSet(graph) >+ { >+ } >+ >+ bool run() >+ { >+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ >+ // An edge A->B is critical if A has multiple successor and B has multiple >+ // predecessors. Thus we fail early if we don't have multiple successors. >+ >+ if (block->numSuccessors() <= 1) >+ continue; >+ >+ for (unsigned i = block->numSuccessors(); i--;) { >+ BasicBlock** successor = &block->successor(i); >+ if ((*successor)->predecessors.size() <= 1) >+ continue; >+ >+ breakCriticalEdge(successor); >+ } >+ } >+ >+ return m_insertionSet.execute(); >+ } >+ >+private: >+ void breakCriticalEdge(BasicBlock** successor) >+ { >+ m_graph.dethread(); >+ >+ BasicBlock* pad = m_insertionSet.insertBefore(*successor); >+ pad->appendNode( >+ m_graph, SpecNone, Jump, (*successor)->at(0)->codeOrigin, OpInfo(*successor)); >+ >+ *successor = pad; >+ } >+ >+ BlockInsertionSet m_insertionSet; >+}; >+ >+bool performCriticalEdgeBreaking(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG Critical Edge Breaking Phase"); >+ return runPhase<CriticalEdgeBreakingPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+ >Index: Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGCriticalEdgeBreakingPhase.h (working copy) >@@ -0,0 +1,47 @@ >+/* >+ * 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 DFGCriticalEdgeBreakingPhase_h >+#define DFGCriticalEdgeBreakingPhase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Inserts dummy basic blocks to break critical edges. An edge A->B is >+// critical if A has multiple successors and B has multiple predessors. >+ >+bool performCriticalEdgeBreaking(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGCriticalEdgeBreakingPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGDCEPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (working copy) >@@ -45,6 +45,8 @@ public: > > bool run() > { >+ ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == SSA); >+ > // First reset the counts to 0 for all nodes. > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { > BasicBlock* block = m_graph.block(blockIndex); >@@ -75,10 +77,29 @@ public: > } > > while (!m_worklist.isEmpty()) { >- Node* node = m_worklist.last(); >- m_worklist.removeLast(); >- ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed. >- DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge); >+ while (!m_worklist.isEmpty()) { >+ Node* node = m_worklist.last(); >+ m_worklist.removeLast(); >+ ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed. >+ DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge); >+ } >+ >+ if (m_graph.m_form == SSA) { >+ // Find Phi->Upsilon edges, which are represented as meta-data in the >+ // Upsilon. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) { >+ Node* node = block->at(nodeIndex); >+ if (node->op() != Upsilon) >+ continue; >+ if (node->phi()->shouldGenerate()) >+ countNode(node); >+ } >+ } >+ } > } > > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { >@@ -94,8 +115,10 @@ public: > continue; > > switch (node->op()) { >- case SetLocal: { >- if (node->child1().isProved() || node->child1().useKind() == UntypedUse) { >+ case SetLocal: >+ case MovHint: { >+ ASSERT((node->op() == SetLocal) == (m_graph.m_form == ThreadedCPS)); >+ if (node->child1().willNotHaveCheck()) { > // Consider the possibility that UInt32ToNumber is dead but its > // child isn't; if so then we should MovHint the child. > if (!node->child1()->shouldGenerate() >@@ -117,8 +140,10 @@ public: > > case GetLocal: > case SetArgument: { >- // Leave them as not shouldGenerate. >- break; >+ if (m_graph.m_form == ThreadedCPS) { >+ // Leave them as not shouldGenerate. >+ break; >+ } > } > > default: { >@@ -126,7 +151,7 @@ public: > for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) { > Edge edge = m_graph.m_varArgChildren[childIdx]; > >- if (!edge || edge.isProved() || edge.useKind() == UntypedUse) >+ if (!edge || edge.willNotHaveCheck()) > continue; > > insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node->codeOrigin, edge); >@@ -158,21 +183,25 @@ private: > { > // We may have an "unproved" untyped use for code that is unreachable. The CFA > // will just not have gotten around to it. >- if (edge.isProved() || edge.useKind() == UntypedUse) >+ if (edge.willNotHaveCheck()) > return; > if (!edge->postfixRef()) > m_worklist.append(edge.node()); > } > >+ void countNode(Node* node) >+ { >+ if (node->postfixRef()) >+ return; >+ m_worklist.append(node); >+ } >+ > void countEdge(Node*, Edge edge) > { > // Don't count edges that are already counted for their type checks. >- if (!(edge.isProved() || edge.useKind() == UntypedUse)) >- return; >- >- if (edge->postfixRef()) >+ if (edge.willHaveCheck()) > return; >- m_worklist.append(edge.node()); >+ countNode(edge.node()); > } > > void eliminateIrrelevantPhantomChildren(Node* node) >@@ -181,7 +210,7 @@ private: > Edge edge = node->children.child(i); > if (!edge) > continue; >- if (edge.isProved() || edge.useKind() == UntypedUse) >+ if (edge.willNotHaveCheck()) > node->children.removeEdge(i--); > } > } >Index: Source/JavaScriptCore/dfg/DFGEdge.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGEdge.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGEdge.cpp (working copy) >@@ -39,6 +39,8 @@ void Edge::dump(PrintStream& out) const > out.print("Check:"); > out.print(useKind(), ":"); > } >+ if (doesKill()) >+ out.print("Kill:"); > out.print(node()); > } > >Index: Source/JavaScriptCore/dfg/DFGEdge.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGEdge.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGEdge.h (working copy) >@@ -39,12 +39,12 @@ class AdjacencyList; > > class Edge { > public: >- explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck) >+ explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck, KillStatus killStatus = DoesNotKill) > #if USE(JSVALUE64) >- : m_encodedWord(makeWord(node, useKind, proofStatus)) >+ : m_encodedWord(makeWord(node, useKind, proofStatus, killStatus)) > #else > : m_node(node) >- , m_encodedWord(makeWord(useKind, proofStatus)) >+ , m_encodedWord(makeWord(useKind, proofStatus, killStatus)) > #endif > { > } >@@ -61,7 +61,7 @@ public: > void setNode(Node* node) > { > #if USE(JSVALUE64) >- m_encodedWord = makeWord(node, useKind(), proofStatus()); >+ m_encodedWord = makeWord(node, useKind(), proofStatus(), killStatus()); > #else > m_node = node; > #endif >@@ -89,7 +89,7 @@ public: > { > ASSERT(node()); > #if USE(JSVALUE64) >- m_encodedWord = makeWord(node(), useKind, proofStatus()); >+ m_encodedWord = makeWord(node(), useKind, proofStatus(), killStatus()); > #else > m_encodedWord = makeWord(useKind, proofStatus()); > #endif >@@ -108,9 +108,9 @@ public: > { > ASSERT(node()); > #if USE(JSVALUE64) >- m_encodedWord = makeWord(node(), useKind(), proofStatus); >+ m_encodedWord = makeWord(node(), useKind(), proofStatus, killStatus()); > #else >- m_encodedWord = makeWord(useKind(), proofStatus); >+ m_encodedWord = makeWord(useKind(), proofStatus, killStatus()); > #endif > } > bool isProved() const >@@ -122,6 +122,36 @@ public: > return proofStatus() == NeedsCheck; > } > >+ bool willNotHaveCheck() const >+ { >+ return isProved() || useKind() == UntypedUse; >+ } >+ bool willHaveCheck() const >+ { >+ return !willNotHaveCheck(); >+ } >+ >+ KillStatus killStatusUnchecked() const >+ { >+ return killStatusForDoesKill(m_encodedWord & 2); >+ } >+ KillStatus killStatus() const >+ { >+ ASSERT(node()); >+ return killStatusUnchecked(); >+ } >+ void setKillStatus(KillStatus killStatus) >+ { >+ ASSERT(node()); >+#if USE(JSVALUE64) >+ m_encodedWord = makeWord(node(), useKind(), proofStatus(), killStatus); >+#else >+ m_encodedWord = makeWord(useKind(), proofStatus(), killStatus); >+#endif >+ } >+ bool doesKill() const { return DFG::doesKill(killStatus()); } >+ bool doesNotKill() const { return !doesKill(); } >+ > bool isSet() const { return !!node(); } > > typedef void* Edge::*UnspecifiedBoolType; >@@ -150,20 +180,20 @@ private: > #if USE(JSVALUE64) > static uint32_t shift() { return 6; } > >- static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus) >+ static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus) > { > ASSERT(sizeof(node) == 8); > uintptr_t shiftedValue = bitwise_cast<uintptr_t>(node) << shift(); > ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node)); > ASSERT(useKind >= 0 && useKind < LastUseKind); >- ASSERT((static_cast<uintptr_t>(LastUseKind) << 1) <= (static_cast<uintptr_t>(1) << shift())); >- return shiftedValue | (static_cast<uintptr_t>(useKind) << 1) | DFG::isProved(proofStatus); >+ ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift())); >+ return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus); > } > > #else >- static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus) >+ static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus, KillStatus killStatus) > { >- return (static_cast<uintptr_t>(useKind) << 1) | DFG::isProved(proofStatus); >+ return (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus); > } > > Node* m_node; >Index: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (working copy) >@@ -901,6 +901,7 @@ private: > > case GetArrayLength: > case Phi: >+ case Upsilon: > case ForwardInt32ToDouble: > case PhantomPutStructure: > case GetIndexedPropertyStorage: >Index: Source/JavaScriptCore/dfg/DFGFlushFormat.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushFormat.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGFlushFormat.cpp (working copy) >@@ -0,0 +1,63 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGFlushFormat.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace WTF { >+ >+using namespace JSC::DFG; >+ >+void printInternal(PrintStream& out, FlushFormat format) >+{ >+ switch (format) { >+ case DeadFlush: >+ out.print("DeadFlush"); >+ return; >+ case FlushedInt32: >+ out.print("FlushedInt32"); >+ return; >+ case FlushedDouble: >+ out.print("FlushedDouble"); >+ return; >+ case FlushedCell: >+ out.print("FlushedCell"); >+ return; >+ case FlushedBoolean: >+ out.print("FlushedBoolean"); >+ return; >+ case FlushedJSValue: >+ out.print("FlushedJSValue"); >+ return; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace WTF >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGFlushFormat.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushFormat.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGFlushFormat.h (working copy) >@@ -0,0 +1,57 @@ >+/* >+ * 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 DFGFlushFormat_h >+#define DFGFlushFormat_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace DFG { >+ >+enum FlushFormat { >+ DeadFlush, >+ FlushedInt32, >+ FlushedDouble, >+ FlushedCell, >+ FlushedBoolean, >+ FlushedJSValue >+}; >+ >+} } // namespace JSC::DFG >+ >+namespace WTF { >+ >+void printInternal(PrintStream&, JSC::DFG::FlushFormat); >+ >+} // namespace WTF >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGFlushFormat_h >+ >Index: Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.cpp (working copy) >@@ -0,0 +1,182 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGFlushLivenessAnalysisPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGBasicBlockInlines.h" >+#include "DFGGraph.h" >+#include "DFGInsertionSet.h" >+#include "DFGPhase.h" >+#include "Operations.h" >+ >+namespace JSC { namespace DFG { >+ >+class FlushLivenessAnalysisPhase : public Phase { >+public: >+ FlushLivenessAnalysisPhase(Graph& graph) >+ : Phase(graph, "flush-liveness analysis") >+ { >+ } >+ >+ bool run() >+ { >+ ASSERT(m_graph.m_form == SSA); >+ >+ // Liveness is a backwards analysis; the roots are the blocks that >+ // end in a terminal (Return/Throw/ThrowReferenceError). For now, we >+ // use a fixpoint formulation since liveness is a rapid analysis with >+ // convergence guaranteed after O(connectivity). >+ >+ // Start by assuming that everything is dead. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ block->ssa->flushFormatAtHead.fill(DeadFlush); >+ block->ssa->flushFormatAtTail.fill(DeadFlush); >+ } >+ >+ do { >+ m_changed = false; >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) >+ process(blockIndex); >+ } while (m_changed); >+ >+ return true; >+ } >+ >+private: >+ void process(BlockIndex blockIndex) >+ { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ return; >+ >+ m_live = block->ssa->flushFormatAtTail; >+ >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) { >+ Node* node = block->at(nodeIndex); >+ >+ switch (node->op()) { >+ case SetLocal: { >+ VariableAccessData* variable = node->variableAccessData(); >+ setForNode(node, variable->local(), variable->flushFormat(), DeadFlush); >+ break; >+ } >+ >+ case Flush: >+ case GetLocal: { >+ VariableAccessData* variable = node->variableAccessData(); >+ FlushFormat format = variable->flushFormat(); >+ setForNode(node, variable->local(), format, format); >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ >+ if (m_live == block->ssa->flushFormatAtHead) >+ return; >+ >+ m_changed = true; >+ block->ssa->flushFormatAtHead = m_live; >+ for (unsigned i = block->predecessors.size(); i--;) { >+ BasicBlock* predecessor = block->predecessors[i]; >+ for (unsigned j = m_live.size(); j--;) { >+ FlushFormat& predecessorFormat = predecessor->ssa->flushFormatAtTail[j]; >+ FlushFormat myFormat = m_live[j]; >+ >+ // Three possibilities: >+ // 1) Predecessor format is Dead, in which case it acquires our format. >+ // 2) Predecessor format is identical to our format, in which case we >+ // do nothing. >+ // 3) Predecessor format is different from our format and it's not Dead, >+ // in which case we have an erroneous set of Flushes and SetLocals. >+ >+ if (predecessorFormat == DeadFlush) { >+ predecessorFormat = myFormat; >+ continue; >+ } >+ >+ if (predecessorFormat == myFormat) >+ continue; >+ >+ dataLog( >+ "Bad Flush merge at edge ", *predecessor, " -> ", *block, >+ ", local variable r", m_live.operandForIndex(j), ": ", *predecessor, >+ " has ", predecessorFormat, " and ", *block, " has ", myFormat, ".\n"); >+ dataLog("IR at time of error:\n"); >+ m_graph.dump(); >+ CRASH(); >+ } >+ } >+ } >+ >+ void setForNode(Node* node, int operand, FlushFormat nodeFormat, FlushFormat newFormat) >+ { >+ FlushFormat& currentFormat = m_live.operand(operand); >+ >+ // Do some useful verification here. It's OK if we think that the >+ // flush format is dead at the time that we see the node. But it's >+ // not OK if both the node and m_live see a FlushFormat and they do >+ // not agree on it. >+ >+ if (currentFormat == DeadFlush || currentFormat == nodeFormat) { >+ currentFormat = newFormat; >+ return; >+ } >+ >+ dataLog( >+ "Bad Flush merge at node ", node, ", r", operand, ": node claims ", nodeFormat, >+ " but backwards flow claims ", currentFormat, ".\n"); >+ dataLog("IR at time of error:\n"); >+ m_graph.dump(); >+ CRASH(); >+ } >+ >+ FlushFormat flushFormat(Node* node) >+ { >+ return node->variableAccessData()->flushFormat(); >+ } >+ >+ bool m_changed; >+ Operands<FlushFormat> m_live; >+}; >+ >+bool performFlushLivenessAnalysis(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG Flush-Liveness Analysis Phase"); >+ return runPhase<FlushLivenessAnalysisPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.h (working copy) >@@ -0,0 +1,48 @@ >+/* >+ * 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 DFGFlushLivenessAnalysisPhase_h >+#define DFGFlushLivenessAnalysisPhase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGCommon.h" >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Computes BasicBlock::ssa->flushFormatAtHead >+ >+bool performFlushLivenessAnalysis(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGFlushLivenessAnalysisPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGGraph.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGGraph.cpp (working copy) >@@ -32,6 +32,7 @@ > #include "FunctionExecutableDump.h" > #include "Operations.h" > #include <wtf/CommaPrinter.h> >+#include <wtf/ListDump.h> > > #if ENABLE(DFG_JIT) > >@@ -235,6 +236,8 @@ void Graph::dump(PrintStream& out, const > } > if (node->hasIndexingType()) > out.print(comma, IndexingTypeDump(node->indexingType())); >+ if (node->hasPhi()) >+ out.print(comma, "^", node->phi()->index()); > if (node->hasExecutionCounter()) > out.print(comma, RawPointer(node->executionCounter())); > if (op == JSConstant) { >@@ -313,23 +316,25 @@ void Graph::dumpBlockHeader(PrintStream& > out.print("\n"); > } > } >- out.print(prefix, " Phi Nodes:"); >- for (size_t i = 0; i < block->phis.size(); ++i) { >- Node* phiNode = block->phis[i]; >- if (!phiNode->shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly) >- continue; >- out.print(" @", phiNode->index(), "<", phiNode->refCount(), ">->("); >- if (phiNode->child1()) { >- out.print("@", phiNode->child1()->index()); >- if (phiNode->child2()) { >- out.print(", @", phiNode->child2()->index()); >- if (phiNode->child3()) >- out.print(", @", phiNode->child3()->index()); >+ if (!block->phis.isEmpty()) { >+ out.print(prefix, " Phi Nodes:"); >+ for (size_t i = 0; i < block->phis.size(); ++i) { >+ Node* phiNode = block->phis[i]; >+ if (!phiNode->shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly) >+ continue; >+ out.print(" @", phiNode->index(), "<", phiNode->refCount(), ">->("); >+ if (phiNode->child1()) { >+ out.print("@", phiNode->child1()->index()); >+ if (phiNode->child2()) { >+ out.print(", @", phiNode->child2()->index()); >+ if (phiNode->child3()) >+ out.print(", @", phiNode->child3()->index()); >+ } > } >+ out.print(")", i + 1 < block->phis.size() ? "," : ""); > } >- out.print(")", i + 1 < block->phis.size() ? "," : ""); >+ out.print("\n"); > } >- out.print("\n"); > } > > void Graph::dump(PrintStream& out) >@@ -343,29 +348,57 @@ void Graph::dump(PrintStream& out) > if (!block) > continue; > dumpBlockHeader(out, "", block, DumpAllPhis); >- out.print(" vars before: "); >- if (block->cfaHasVisited) >- dumpOperands(block->valuesAtHead, out); >- else >- out.print("<empty>"); >- out.print("\n"); >- out.print(" var links: "); >- dumpOperands(block->variablesAtHead, out); >- out.print("\n"); >+ switch (m_form) { >+ case LoadStore: >+ case ThreadedCPS: { >+ out.print(" vars before: "); >+ if (block->cfaHasVisited) >+ out.print(block->valuesAtHead); >+ else >+ out.print("<empty>"); >+ out.print("\n"); >+ out.print(" var links: "); >+ dumpOperands(block->variablesAtHead, out); >+ out.print("\n"); >+ break; >+ } >+ >+ case SSA: { >+ RELEASE_ASSERT(block->ssa); >+ out.print(" Flush format: ", block->ssa->flushFormatAtHead, "\n"); >+ out.print(" Availability: ", block->ssa->availabilityAtHead, "\n"); >+ out.print(" Live: ", nodeListDump(block->ssa->liveAtHead), "\n"); >+ out.print(" Values: ", nodeMapDump(block->ssa->valuesAtHead), "\n"); >+ break; >+ } } > for (size_t i = 0; i < block->size(); ++i) { > dumpCodeOrigin(out, "", lastNode, block->at(i)); > dump(out, "", block->at(i)); > lastNode = block->at(i); > } >- out.print(" vars after: "); >- if (block->cfaHasVisited) >- dumpOperands(block->valuesAtTail, out); >- else >- out.print("<empty>"); >- out.print("\n"); >- out.print(" var links: "); >- dumpOperands(block->variablesAtTail, out); >- out.print("\n"); >+ switch (m_form) { >+ case LoadStore: >+ case ThreadedCPS: { >+ out.print(" vars after: "); >+ if (block->cfaHasVisited) >+ out.print(block->valuesAtTail); >+ else >+ out.print("<empty>"); >+ out.print("\n"); >+ out.print(" var links: "); >+ dumpOperands(block->variablesAtTail, out); >+ out.print("\n"); >+ break; >+ } >+ >+ case SSA: { >+ RELEASE_ASSERT(block->ssa); >+ out.print(" Flush format: ", block->ssa->flushFormatAtTail, "\n"); >+ out.print(" Availability: ", block->ssa->availabilityAtTail, "\n"); >+ out.print(" Live: ", nodeListDump(block->ssa->liveAtTail), "\n"); >+ out.print(" Values: ", nodeMapDump(block->ssa->valuesAtTail), "\n"); >+ break; >+ } } > } > } > >@@ -478,6 +511,28 @@ void Graph::substituteGetLocal(BasicBloc > break; > } > } >+ >+void Graph::addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock* block) >+{ >+ if (seen.contains(block)) >+ return; >+ >+ result.append(block); >+ worklist.append(block); >+ seen.add(block); >+} >+ >+void Graph::getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result) >+{ >+ Vector<BasicBlock*, 16> worklist; >+ HashSet<BasicBlock*> seen; >+ addForDepthFirstSort(result, worklist, seen, block(0)); >+ while (!worklist.isEmpty()) { >+ BasicBlock* block = worklist.takeLast(); >+ for (unsigned i = block->numSuccessors(); i--;) >+ addForDepthFirstSort(result, worklist, seen, block->successor(i)); >+ } >+} > > } } // namespace JSC::DFG > >Index: Source/JavaScriptCore/dfg/DFGGraph.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGGraph.h (working copy) >@@ -641,6 +641,8 @@ public: > > void invalidateCFG(); > >+ void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result); >+ > Profiler::Compilation* compilation() { return m_plan.compilation.get(); } > > DesiredIdentifiers& identifiers() { return m_plan.identifiers; } >@@ -679,6 +681,7 @@ public: > private: > > void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor); >+ void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*); > > AddSpeculationMode addImmediateShouldSpeculateInteger(Node* add, bool variableShouldSpeculateInteger, Node* immediate) > { >Index: Source/JavaScriptCore/dfg/DFGInsertionSet.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInsertionSet.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGInsertionSet.h (working copy) >@@ -31,26 +31,12 @@ > #if ENABLE(DFG_JIT) > > #include "DFGGraph.h" >+#include <wtf/Insertion.h> > #include <wtf/Vector.h> > > namespace JSC { namespace DFG { > >-class Insertion { >-public: >- Insertion() { } >- >- Insertion(size_t index, Node* element) >- : m_index(index) >- , m_element(element) >- { >- } >- >- size_t index() const { return m_index; } >- Node* element() const { return m_element; } >-private: >- size_t m_index; >- Node* m_element; >-}; >+typedef WTF::Insertion<Node*> Insertion; > > class InsertionSet { > public: >@@ -81,20 +67,7 @@ public: > > void execute(BasicBlock* block) > { >- if (!m_insertions.size()) >- return; >- block->grow(block->size() + m_insertions.size()); >- size_t lastIndex = block->size(); >- for (size_t indexInInsertions = m_insertions.size(); indexInInsertions--;) { >- Insertion& insertion = m_insertions[indexInInsertions]; >- size_t firstIndex = insertion.index() + indexInInsertions; >- size_t indexOffset = indexInInsertions + 1; >- for (size_t i = lastIndex; --i > firstIndex;) >- block->at(i) = block->at(i - indexOffset); >- block->at(firstIndex) = insertion.element(); >- lastIndex = firstIndex; >- } >- m_insertions.resize(0); >+ executeInsertions(*block, m_insertions); > } > private: > Graph& m_graph; >Index: Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp (working copy) >@@ -0,0 +1,157 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGLivenessAnalysisPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGBasicBlockInlines.h" >+#include "DFGGraph.h" >+#include "DFGInsertionSet.h" >+#include "DFGPhase.h" >+#include "Operations.h" >+ >+namespace JSC { namespace DFG { >+ >+class LivenessAnalysisPhase : public Phase { >+public: >+ LivenessAnalysisPhase(Graph& graph) >+ : Phase(graph, "liveness analysis") >+ { >+ } >+ >+ bool run() >+ { >+ ASSERT(m_graph.m_form == SSA); >+ >+ // Liveness is a backwards analysis; the roots are the blocks that >+ // end in a terminal (Return/Throw/ThrowReferenceError). For now, we >+ // use a fixpoint formulation since liveness is a rapid analysis with >+ // convergence guaranteed after O(connectivity). >+ >+ // Start by assuming that everything is dead. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ block->ssa->liveAtHead.clear(); >+ block->ssa->liveAtTail.clear(); >+ } >+ >+ do { >+ m_changed = false; >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) >+ process(blockIndex); >+ } while (m_changed); >+ >+ return true; >+ } >+ >+private: >+ void process(BlockIndex blockIndex) >+ { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ return; >+ >+ // FIXME: It's likely that this can be improved, for static analyses that use >+ // HashSets. https://bugs.webkit.org/show_bug.cgi?id=118455 >+ m_live = block->ssa->liveAtTail; >+ >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) { >+ Node* node = block->at(nodeIndex); >+ >+ // Given an Upsilon: >+ // >+ // n: Upsilon($p, @x) >+ // >+ // We say that it def's @p and @n and uses @x. >+ // >+ // Given a Phi: >+ // >+ // p: Phi() >+ // >+ // We say nothing. It's neither a use nor a def. >+ // >+ // Given a node: >+ // >+ // n: Thingy(@a, @b, @c) >+ // >+ // We say that it def's @n and uses @a, @b, @c. >+ >+ switch (node->op()) { >+ case Upsilon: { >+ Node* phi = node->phi(); >+ m_live.remove(phi); >+ m_live.remove(node); >+ m_live.add(node->child1().node()); >+ break; >+ } >+ >+ case Phi: { >+ break; >+ } >+ >+ default: >+ m_live.remove(node); >+ DFG_NODE_DO_TO_CHILDREN(m_graph, node, addChildUse); >+ break; >+ } >+ } >+ >+ if (m_live == block->ssa->liveAtHead) >+ return; >+ >+ m_changed = true; >+ block->ssa->liveAtHead = m_live; >+ for (unsigned i = block->predecessors.size(); i--;) >+ block->ssa->liveAtTail.add(m_live.begin(), m_live.end()); >+ } >+ >+ void addChildUse(Node*, Edge& edge) >+ { >+ addChildUse(edge); >+ } >+ >+ void addChildUse(Edge& edge) >+ { >+ edge.setKillStatus(m_live.add(edge.node()).isNewEntry ? DoesKill : DoesNotKill); >+ } >+ >+ bool m_changed; >+ HashSet<Node*> m_live; >+}; >+ >+bool performLivenessAnalysis(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG Liveness Analysis Phase"); >+ return runPhase<LivenessAnalysisPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.h (working copy) >@@ -0,0 +1,48 @@ >+/* >+ * 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 DFGLivenessAnalysisPhase_h >+#define DFGLivenessAnalysisPhase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGCommon.h" >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Computes BasicBlock::ssa->liveAtHead/liveAtTail. >+ >+bool performLivenessAnalysis(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGLivenessAnalysisPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -45,6 +45,7 @@ > #include "SpeculatedType.h" > #include "StructureSet.h" > #include "ValueProfile.h" >+#include <wtf/ListDump.h> > > namespace JSC { namespace DFG { > >@@ -538,6 +539,17 @@ struct Node { > return static_cast<VirtualRegister>(m_opInfo); > } > >+ bool hasPhi() >+ { >+ return op() == Upsilon; >+ } >+ >+ Node* phi() >+ { >+ ASSERT(hasPhi()); >+ return bitwise_cast<Node*>(m_opInfo); >+ } >+ > bool hasIdentifier() > { > switch (op()) { >@@ -773,16 +785,16 @@ struct Node { > m_opInfo2 = bitwise_cast<uintptr_t>(block); > } > >- BasicBlock* takenBlock() >+ BasicBlock*& takenBlock() > { > ASSERT(isBranch() || isJump()); >- return bitwise_cast<BasicBlock*>(m_opInfo); >+ return *bitwise_cast<BasicBlock**>(&m_opInfo); > } > >- BasicBlock* notTakenBlock() >+ BasicBlock*& notTakenBlock() > { > ASSERT(isBranch()); >- return bitwise_cast<BasicBlock*>(m_opInfo2); >+ return *bitwise_cast<BasicBlock**>(&m_opInfo2); > } > > SwitchData* switchData() >@@ -805,7 +817,7 @@ struct Node { > } > } > >- BasicBlock* successor(unsigned index) >+ BasicBlock*& successor(unsigned index) > { > if (isSwitch()) { > if (index < switchData()->cases.size()) >@@ -820,11 +832,11 @@ struct Node { > return notTakenBlock(); > default: > RELEASE_ASSERT_NOT_REACHED(); >- return 0; >+ return takenBlock(); > } > } > >- BasicBlock* successorForCondition(bool condition) >+ BasicBlock*& successorForCondition(bool condition) > { > ASSERT(isBranch()); > return condition ? takenBlock() : notTakenBlock(); >@@ -1399,6 +1411,23 @@ public: > Node* replacement; > }; > >+inline bool nodeComparator(Node* a, Node* b) >+{ >+ return a->index() < b->index(); >+} >+ >+template<typename T> >+CString nodeListDump(const T& nodeList) >+{ >+ return sortedListDump(nodeList, nodeComparator); >+} >+ >+template<typename T> >+CString nodeMapDump(const T& nodeMap) >+{ >+ return sortedMapDump(nodeMap, nodeComparator); >+} >+ > } } // namespace JSC::DFG > > namespace WTF { >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -63,6 +63,7 @@ namespace JSC { namespace DFG { > macro(MovHint, NodeDoesNotExit) \ > macro(ZombieHint, NodeDoesNotExit) \ > macro(Phantom, NodeMustGenerate) \ >+ macro(Upsilon, NodeDoesNotExit | NodeRelevantToOSR) \ > macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \ > macro(Flush, NodeMustGenerate | NodeDoesNotExit) \ > macro(PhantomLocal, NodeMustGenerate | NodeDoesNotExit) \ >Index: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (working copy) >@@ -0,0 +1,130 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGOSRAvailabilityAnalysisPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGBasicBlockInlines.h" >+#include "DFGGraph.h" >+#include "DFGInsertionSet.h" >+#include "DFGPhase.h" >+#include "Operations.h" >+ >+namespace JSC { namespace DFG { >+ >+class OSRAvailabilityAnalysisPhase : public Phase { >+public: >+ OSRAvailabilityAnalysisPhase(Graph& graph) >+ : Phase(graph, "OSR availability analysis") >+ { >+ } >+ >+ bool run() >+ { >+ ASSERT(m_graph.m_form == SSA); >+ >+ Vector<BasicBlock*> depthFirst; >+ m_graph.getBlocksInDepthFirstOrder(depthFirst); >+ >+ for (unsigned i = 0; i < depthFirst.size(); ++i) { >+ BasicBlock* block = depthFirst[i]; >+ block->ssa->availabilityAtHead.fill(0); >+ block->ssa->availabilityAtTail.fill(0); >+ } >+ >+ for (unsigned i = 0; i < depthFirst.size(); ++i) { >+ BasicBlock* block = depthFirst[i]; >+ >+ // We edit availabilityAtTail in-place, but first initialize it to >+ // availabilityAtHead. >+ Operands<Node*>& availability = block->ssa->availabilityAtTail; >+ availability = block->ssa->availabilityAtHead; >+ >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ switch (node->op()) { >+ case SetLocal: >+ case MovHint: >+ case MovHintAndCheck: { >+ availability.operand(node->local()) = node->child1().node(); >+ break; >+ } >+ >+ case ZombieHint: { >+ availability.operand(node->local()) = 0; >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ >+ for (unsigned j = block->numSuccessors(); j--;) { >+ BasicBlock* successor = block->successor(j); >+ Operands<Node*>& successorAvailability = successor->ssa->availabilityAtHead; >+ for (unsigned k = availability.size(); k--;) { >+ Node* myNode = availability[k]; >+ if (!myNode) >+ continue; >+ >+ if (!block->ssa->liveAtHead.contains(myNode)) >+ continue; >+ >+ // Note that this may overwrite availability with a bogus node >+ // at merge points. This is fine, since merge points have >+ // MovHint(Phi)'s to work around this. The outcome of this is >+ // you might have a program in which a node happens to remain >+ // live into some block B, and separately (due to copy >+ // propagation) just one of the predecessors of B issued a >+ // MovHint putting that node into some local. Then in B we might >+ // think that that node is a valid value for that local. Of >+ // course if that local was actually live in B, B would have a >+ // Phi for it. So essentially we'll have OSR exit dropping this >+ // node's value into the local when we otherwise (in the DFG) >+ // would have dropped undefined into the local. This seems >+ // harmless. >+ >+ successorAvailability[k] = myNode; >+ } >+ } >+ } >+ >+ return true; >+ } >+}; >+ >+bool performOSRAvailabilityAnalysis(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG OSR Availability Analysis Phase"); >+ return runPhase<OSRAvailabilityAnalysisPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h (working copy) >@@ -0,0 +1,50 @@ >+/* >+ * 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 DFGOSRAvailabilityAnalysisPhase_h >+#define DFGOSRAvailabilityAnalysisPhase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGCommon.h" >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Computes BasicBlock::ssa->availabiltiyAtHead/Tail. This relies on liveness >+// analysis phase having been run and the graph not having been transformed >+// after that. >+ >+bool performOSRAvailabilityAnalysis(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGOSRAvailabilityAnalysisPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGPlan.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPlan.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGPlan.cpp (working copy) >@@ -36,12 +36,17 @@ > #include "DFGCPSRethreadingPhase.h" > #include "DFGCSEPhase.h" > #include "DFGConstantFoldingPhase.h" >+#include "DFGCriticalEdgeBreakingPhase.h" > #include "DFGDCEPhase.h" > #include "DFGFailedFinalizer.h" >+#include "DFGFlushLivenessAnalysisPhase.h" > #include "DFGFixupPhase.h" > #include "DFGJITCompiler.h" >+#include "DFGLivenessAnalysisPhase.h" >+#include "DFGOSRAvailabilityAnalysisPhase.h" > #include "DFGPredictionInjectionPhase.h" > #include "DFGPredictionPropagationPhase.h" >+#include "DFGSSAConversionPhase.h" > #include "DFGTypeCheckHoistingPhase.h" > #include "DFGUnificationPhase.h" > #include "DFGValidate.h" >@@ -183,21 +188,21 @@ Plan::CompilationPath Plan::compileInThr > > performStoreElimination(dfg); > performCPSRethreading(dfg); >- >- // Note that DCE is necessary even in the FTL, because only we know what is >- // live-in-bytecode. The FTL uses this information to determine when OSR exit >- // values should be wired to LValues, versus being wired to ExitValue::dead(). >- // This is distinct from what ZombieHint gives us: ZombieHint says that the >- // value in the given bytecode local is always dead; the reference counts that >- // DCE produces tell us that the value is live for a while but eventually >- // dies, and it tells us exactly when the death point is. >- performDCE(dfg); > > #if ENABLE(FTL_JIT) > if (Options::useExperimentalFTL() > && compileMode == CompileFunction > && FTL::canCompile(dfg)) { > >+ performCriticalEdgeBreaking(dfg); >+ performSSAConversion(dfg); >+ performLivenessAnalysis(dfg); >+ performCFA(dfg); >+ performDCE(dfg); // We rely on this to convert dead SetLocals into the appropriate hint, and to kill dead code that won't be recognized as dead by LLVM. >+ performLivenessAnalysis(dfg); >+ performFlushLivenessAnalysis(dfg); >+ performOSRAvailabilityAnalysis(dfg); >+ > dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:"); > > // FIXME: Support OSR entry. >@@ -215,6 +220,7 @@ Plan::CompilationPath Plan::compileInThr > } > #endif // ENABLE(FTL_JIT) > >+ performDCE(dfg); > performVirtualRegisterAllocation(dfg); > dumpAndVerifyGraph(dfg, "Graph after optimization:"); > >Index: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (working copy) >@@ -472,14 +472,19 @@ private: > case ZombieHint: { > // This node should never be visible at this stage of compilation. It is > // inserted by fixup(), which follows this phase. >- CRASH(); >+ RELEASE_ASSERT_NOT_REACHED(); > break; > } > > case Phi: > // Phis should not be visible here since we're iterating the all-but-Phi's > // part of basic blocks. >- CRASH(); >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ >+ case Upsilon: >+ // These don't get inserted until we go into SSA. >+ RELEASE_ASSERT_NOT_REACHED(); > break; > > case GetScope: >@@ -540,7 +545,7 @@ private: > break; > > case LastNodeType: >- CRASH(); >+ RELEASE_ASSERT_NOT_REACHED(); > break; > #else > default: >Index: Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (working copy) >@@ -0,0 +1,373 @@ >+/* >+ * 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. >+ */ >+ >+#include "config.h" >+#include "DFGSSAConversionPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGBasicBlockInlines.h" >+#include "DFGGraph.h" >+#include "DFGInsertionSet.h" >+#include "DFGPhase.h" >+#include "Operations.h" >+ >+namespace JSC { namespace DFG { >+ >+class SSAConversionPhase : public Phase { >+public: >+ SSAConversionPhase(Graph& graph) >+ : Phase(graph, "SSA conversion") >+ , m_insertionSet(graph) >+ , m_changed(false) >+ { >+ } >+ >+ bool run() >+ { >+ RELEASE_ASSERT(m_graph.m_form == ThreadedCPS); >+ >+ // Figure out which SetLocal's need flushing. Need to do this while the >+ // Phi graph is still intact. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) { >+ Node* node = block->at(nodeIndex); >+ if (node->op() != Flush) >+ continue; >+ addFlushedLocalOp(node); >+ } >+ } >+ while (!m_flushedLocalOpWorklist.isEmpty()) { >+ Node* node = m_flushedLocalOpWorklist.takeLast(); >+ ASSERT(m_flushedLocalOps.contains(node)); >+ DFG_NODE_DO_TO_CHILDREN(m_graph, node, addFlushedLocalEdge); >+ } >+ >+ // Eliminate all duplicate or self-pointing Phi edges. This means that >+ // we transform: >+ // >+ // p: Phi(@n1, @n2, @n3) >+ // >+ // into: >+ // >+ // p: Phi(@x) >+ // >+ // if each @ni in {@n1, @n2, @n3} is either equal to @p to is equal >+ // to @x, for exactly one other @x. Additionally, trivial Phis (i.e. >+ // p: Phi(@x)) are forwarded, so that if have an edge to such @p, we >+ // replace it with @x. This loop does this for Phis only; later we do >+ // such forwarding for Phi references found in other nodes. >+ // >+ // See Aycock and Horspool in CC'00 for a better description of what >+ // we're doing here. >+ do { >+ m_changed = false; >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (unsigned phiIndex = block->phis.size(); phiIndex--;) { >+ Node* phi = block->phis[phiIndex]; >+ if (phi->variableAccessData()->isCaptured()) >+ continue; >+ forwardPhiChildren(phi); >+ deduplicateChildren(phi); >+ } >+ } >+ } while (m_changed); >+ >+ // For each basic block, for each local live at the head of that block, >+ // figure out what node we should be referring to instead of that local. >+ // If it turns out to be a non-trivial Phi, make sure that to create an >+ // SSA Phi and Upsilons in predecessor blocks. We reuse >+ // BasicBlock::variablesAtHead for tracking which nodes to refer to. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ >+ for (unsigned i = block->variablesAtHead.size(); i--;) { >+ Node* node = block->variablesAtHead[i]; >+ if (!node) >+ continue; >+ >+ VariableAccessData* variable = node->variableAccessData(); >+ if (variable->isCaptured()) { >+ // Poison this entry in variablesAtHead because we don't >+ // want anyone to try to refer to it, if the variable is >+ // captured. >+ block->variablesAtHead[i] = 0; >+ continue; >+ } >+ >+ switch (node->op()) { >+ case Phi: >+ case SetArgument: >+ break; >+ case Flush: >+ case GetLocal: >+ case PhantomLocal: >+ node = node->child1().node(); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ ASSERT(node->op() == Phi || node->op() == SetArgument); >+ >+ if (node->op() == Phi) { >+ Edge edge = node->children.justOneChild(); >+ if (edge) >+ node = edge.node(); >+ else { >+ // It's a non-trivial Phi. >+ // FIXME: We should set the Phi's type (i.e. NodeResultMask) to >+ // reflect the VariableAccessData's unboxing. This will make it >+ // easier for the backend to figure out which value to use for >+ // Upsilons, and what type to use for the Phi itself. >+ >+ NodeFlags result; >+ if (variable->shouldUnboxIfPossible()) { >+ if (variable->shouldUseDoubleFormat()) >+ result = NodeResultNumber; >+ else { >+ SpeculatedType prediction = variable->argumentAwarePrediction(); >+ if (isInt32Speculation(prediction)) >+ result = NodeResultInt32; >+ else if (isBooleanSpeculation(prediction)) >+ result = NodeResultBoolean; >+ else >+ result = NodeResultJS; >+ } >+ } else >+ result = NodeResultJS; >+ >+ node = m_insertionSet.insertNode(0, SpecNone, Phi, node->codeOrigin); >+ node->mergeFlags(result); >+ ASSERT((node->flags() & NodeResultMask) == result); >+ >+ for (unsigned j = block->predecessors.size(); j--;) { >+ BasicBlock* predecessor = block->predecessors[j]; >+ predecessor->appendNonTerminal( >+ m_graph, SpecNone, Upsilon, block->last()->codeOrigin, >+ OpInfo(node), Edge(predecessor->variablesAtTail[i])); >+ } >+ >+ m_insertionSet.insertNode( >+ 0, SpecNone, MovHint, node->codeOrigin, OpInfo(variable), >+ Edge(node)); >+ } >+ } >+ >+ block->variablesAtHead[i] = node; >+ } >+ >+ m_insertionSet.execute(block); >+ } >+ >+ // Convert operations over locals into operations over SSA nodes. >+ // - GetLocal over captured variables lose their phis. >+ // - GetLocal over uncaptured variables die and get replaced with references >+ // to the node specified by variablesAtHead. >+ // - SetLocal gets NodeMustGenerate if it's flushed, or turns into a >+ // MovHint otherwise. >+ // - Flush loses its children but remains, because we want to know when a >+ // flushed SetLocal's value is no longer needed. This also makes it simpler >+ // to reason about the format of a local, since we can just fold it into the >+ // backwards analysis that LivenessAnalysisPhase does. As part of the >+ // backwards analysis, we say that the type of a local can be either >+ // int32, double, value, or dead. >+ // - PhantomLocal becomes Phantom, and its child is whatever is specified >+ // by variablesAtHead. >+ // - SetArgument turns into GetLocal. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) >+ block->at(nodeIndex)->replacement = 0; >+ >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ >+ m_graph.performSubstitution(node); >+ >+ switch (node->op()) { >+ case SetLocal: { >+ VariableAccessData* variable = node->variableAccessData(); >+ if (variable->isCaptured() || m_flushedLocalOps.contains(node)) >+ node->mergeFlags(NodeMustGenerate); >+ else >+ node->setOpAndDefaultFlags(MovHint); >+ break; >+ } >+ >+ case GetLocal: { >+ node->children.reset(); >+ VariableAccessData* variable = node->variableAccessData(); >+ if (variable->isCaptured()) >+ break; >+ node->convertToPhantom(); >+ node->replacement = block->variablesAtHead.operand(variable->local()); >+ break; >+ } >+ >+ case Flush: { >+ node->children.reset(); >+ break; >+ } >+ >+ case PhantomLocal: { >+ VariableAccessData* variable = node->variableAccessData(); >+ if (variable->isCaptured()) >+ break; >+ node->child1().setNode(block->variablesAtHead.operand(variable->local())); >+ node->convertToPhantom(); >+ break; >+ } >+ >+ case SetArgument: { >+ node->setOpAndDefaultFlags(GetLocal); >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ } >+ >+ // Free all phis and reset variables vectors. >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (unsigned phiIndex = block->phis.size(); phiIndex--;) >+ m_graph.m_allocator.free(block->phis[phiIndex]); >+ block->phis.clear(); >+ block->variablesAtHead.clear(); >+ block->variablesAtTail.clear(); >+ block->valuesAtHead.clear(); >+ block->valuesAtHead.clear(); >+ block->ssa = adoptPtr(new BasicBlock::SSAData(block)); >+ } >+ >+ m_graph.m_form = SSA; >+ return true; >+ } >+ >+private: >+ void forwardPhiChildren(Node* node) >+ { >+ for (unsigned i = 0; i < AdjacencyList::Size; ++i) { >+ Edge& edge = node->children.child(i); >+ if (!edge) >+ continue; >+ m_changed |= forwardPhiEdge(edge); >+ } >+ } >+ >+ Node* forwardPhi(Node* node) >+ { >+ for (;;) { >+ switch (node->op()) { >+ case Phi: { >+ Edge edge = node->children.justOneChild(); >+ if (!edge) >+ return node; >+ return edge.node(); >+ } >+ case GetLocal: >+ case SetLocal: >+ if (node->variableAccessData()->isCaptured()) >+ return node; >+ return node->child1().node(); >+ default: >+ return node; >+ } >+ } >+ } >+ >+ bool forwardPhiEdge(Edge& edge) >+ { >+ Node* newNode = forwardPhi(edge.node()); >+ if (newNode == edge.node()) >+ return false; >+ edge.setNode(newNode); >+ return true; >+ } >+ >+ void deduplicateChildren(Node* node) >+ { >+ for (unsigned i = 0; i < AdjacencyList::Size; ++i) { >+ Edge edge = node->children.child(i); >+ if (!edge) >+ break; >+ if (edge == node) { >+ node->children.removeEdge(i--); >+ m_changed = true; >+ continue; >+ } >+ for (unsigned j = i + 1; j < AdjacencyList::Size; ++j) { >+ if (node->children.child(j) == edge) { >+ node->children.removeEdge(j--); >+ m_changed = true; >+ } >+ } >+ } >+ } >+ >+ void addFlushedLocalOp(Node* node) >+ { >+ if (m_flushedLocalOps.contains(node)) >+ return; >+ m_flushedLocalOps.add(node); >+ m_flushedLocalOpWorklist.append(node); >+ } >+ >+ void addFlushedLocalEdge(Node*, Edge edge) >+ { >+ addFlushedLocalOp(edge.node()); >+ } >+ >+ InsertionSet m_insertionSet; >+ HashSet<Node*> m_flushedLocalOps; >+ Vector<Node*> m_flushedLocalOpWorklist; >+ bool m_changed; >+}; >+ >+bool performSSAConversion(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG SSA Conversion Phase"); >+ return runPhase<SSAConversionPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGSSAConversionPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSSAConversionPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGSSAConversionPhase.h (working copy) >@@ -0,0 +1,104 @@ >+/* >+ * 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 DFGSSAConversionPhase_h >+#define DFGSSAConversionPhase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Convert ThreadedCPS form into SSA form. This results in a form that has: >+// >+// - Roughly minimal Phi's. We use the Aycock & Horspool fixpoint for >+// converting the CPS maximal Phis into SSA minimal Phis, with the caveat >+// that irreducible control flow may result in some missed opportunities >+// for Phi reduction. >+// >+// - No uses of GetLocal/SetLocal except for captured variables and flushes. >+// After this, any remaining SetLocal means Flush. Flush nodes are >+// eliminated. PhantomLocals become Phantoms. Nodes may may have children >+// that are in another basic block. >+// >+// - MovHints are used for OSR information, and are themselves minimal. >+// A MovHint will occur at some point after the assigning, and at Phi >+// points. >+// >+// - Unlike conventional SSA in which Phi functions refer to predecessors >+// and values, our SSA uses Upsilon functions to indicate values in >+// predecessors. A merge will look like: >+// >+// labelA: >+// a: Thingy(...) >+// b: Upsilon(^e, @a) >+// Jump(labelC) >+// >+// labelB: >+// c: OtherThingy(...) >+// d: Upsilon(^e, @c) >+// Jump(labelC) >+// >+// labelC: >+// e: Phi() >+// >+// Note that the Phi has no children, but the predecessors have Upsilons >+// that have a weak reference to the Phi (^e instead of @e; we store it >+// in the OpInfo rather than the AdjacencyList). Think of the Upsilon >+// as "assigning" to the "variable" associated with the Phi, and that >+// this is the one place in SSA form where you can have multiple >+// assignments. >+// >+// This implies some other loosenings of SSA. For example, an Upsilon >+// may precede a Phi in the same basic block; this may arise after CFG >+// simplification. Although it's profitable for CFG simplification (or >+// some other phase) to remove these, it's not strictly necessary. As >+// well, this form allows the Upsilon to be in any block that dominates >+// the predecessor block of the Phi, which allows for block splitting to >+// ignore the possibility of introducing an extra edge between the Phi >+// and the predecessor (though normal SSA would allow this, also, with >+// the caveat that the Phi predecessor block lists would have to be >+// updated). >+// >+// The easiest way to convert from this SSA form into a different SSA >+// form is to redo SSA conversion for Phi functions. That is, treat each >+// Phi in our IR as a non-SSA variable in the foreign IR (so, as an >+// alloca in LLVM IR, for example); the Upsilons that refer to the Phi >+// become stores and the Phis themselves become loads. >+// >+// Fun fact: Upsilon is so named because it comes before Phi in the >+// alphabet. It can be written as "Y". >+ >+bool performSSAConversion(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGSSAConversionPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (working copy) >@@ -4395,7 +4395,6 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >- case Phi: > case Flush: > break; > >@@ -4829,6 +4828,8 @@ void SpeculativeJIT::compile(Node* node) > break; > > case LastNodeType: >+ case Phi: >+ case Upsilon: > RELEASE_ASSERT_NOT_REACHED(); > break; > } >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4296,7 +4296,6 @@ void SpeculativeJIT::compile(Node* node) > } > > case Flush: >- case Phi: > break; > > case Breakpoint: >@@ -4690,6 +4689,8 @@ void SpeculativeJIT::compile(Node* node) > break; > > case LastNodeType: >+ case Phi: >+ case Upsilon: > RELEASE_ASSERT_NOT_REACHED(); > break; > } >Index: Source/JavaScriptCore/dfg/DFGValidate.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGValidate.cpp (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGValidate.cpp (working copy) >@@ -81,22 +81,21 @@ public: > V_EQUAL((static_cast<VirtualRegister>(i), 0), static_cast<Node*>(0), root->variablesAtHead.local(i)); > > // Validate ref counts and uses. >- HashMap<Node*, unsigned> myRefCounts; > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { > BasicBlock* block = m_graph.block(blockIndex); >- if (!block || !block->isReachable) >+ if (!block) > continue; >+ VALIDATE((block), block->isReachable); > for (size_t i = 0; i < block->numNodes(); ++i) >- myRefCounts.add(block->node(i), 0); >+ m_myRefCounts.add(block->node(i), 0); > } >- HashSet<Node*> acceptableNodes; > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { > BasicBlock* block = m_graph.block(blockIndex); >- if (!block || !block->isReachable) >+ if (!block) > continue; > for (size_t i = 0; i < block->numNodes(); ++i) { > Node* node = block->node(i); >- acceptableNodes.add(node); >+ m_acceptableNodes.add(node); > if (!node->shouldGenerate()) > continue; > for (unsigned j = 0; j < m_graph.numChildren(node); ++j) { >@@ -108,7 +107,13 @@ public: > if (!edge) > continue; > >- myRefCounts.find(edge.node())->value++; >+ m_myRefCounts.find(edge.node())->value++; >+ >+ if (m_graph.m_form == SSA) { >+ // In SSA, all edges must hasResult(). >+ VALIDATE((node, edge), edge->hasResult()); >+ continue; >+ } > > // Unless I'm a Flush, Phantom, GetLocal, or Phi, my children should hasResult(). > switch (node->op()) { >@@ -148,6 +153,9 @@ public: > case ThreadedCPS: > VALIDATE((node, edge), edge->hasResult()); > break; >+ case SSA: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; > } > break; > default: >@@ -157,9 +165,44 @@ public: > } > } > } >+ >+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (size_t i = 0; i < block->numNodes(); ++i) { >+ Node* node = block->node(i); >+ if (m_graph.m_refCountState == ExactRefCount) >+ V_EQUAL((node), m_myRefCounts.get(node), node->adjustedRefCount()); >+ else >+ V_EQUAL((node), node->refCount(), 1); >+ } >+ } >+ >+ switch (m_graph.m_form) { >+ case LoadStore: >+ case ThreadedCPS: >+ validateCPS(); >+ break; >+ >+ case SSA: >+ // FIXME: Implement SSA verification. >+ break; >+ } >+ } >+ >+private: >+ Graph& m_graph; >+ GraphDumpMode m_graphDumpMode; >+ >+ HashMap<Node*, unsigned> m_myRefCounts; >+ HashSet<Node*> m_acceptableNodes; >+ >+ void validateCPS() >+ { > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { > BasicBlock* block = m_graph.block(blockIndex); >- if (!block || !block->isReachable) >+ if (!block) > continue; > > HashSet<Node*> phisInThisBlock; >@@ -170,15 +213,11 @@ public: > nodesInThisBlock.add(node); > if (block->isPhiIndex(i)) > phisInThisBlock.add(node); >- if (m_graph.m_refCountState == ExactRefCount) >- V_EQUAL((node), myRefCounts.get(node), node->adjustedRefCount()); >- else >- V_EQUAL((node), node->refCount(), 1); > for (unsigned j = 0; j < m_graph.numChildren(node); ++j) { > Edge edge = m_graph.child(node, j); > if (!edge) > continue; >- VALIDATE((node, edge), acceptableNodes.contains(edge.node())); >+ VALIDATE((node, edge), m_acceptableNodes.contains(edge.node())); > } > } > >@@ -228,7 +267,6 @@ public: > for (unsigned k = 0; k < block->predecessors.size(); ++k) { > BasicBlock* prevBlock = block->predecessors[k]; > VALIDATE((block->predecessors[k]), prevBlock); >- VALIDATE((block->predecessors[k]), prevBlock->isReachable); > Node* prevNode = prevBlock->variablesAtTail.operand(local); > // If we have a Phi that is not referring to *this* block then all predecessors > // must have that local available. >@@ -321,7 +359,7 @@ public: > break; > // Ignore GetLocal's that we know to be dead, but that the graph > // doesn't yet know to be dead. >- if (!myRefCounts.get(node)) >+ if (!m_myRefCounts.get(node)) > break; > if (m_graph.m_form == ThreadedCPS) > VALIDATE((node, block), getLocalPositions.operand(node->local()) == notSet); >@@ -355,10 +393,6 @@ public: > } > } > >-private: >- Graph& m_graph; >- GraphDumpMode m_graphDumpMode; >- > void checkOperand( > BasicBlock* block, Operands<size_t>& getLocalPositions, > Operands<size_t>& setLocalPositions, int operand) >Index: Source/JavaScriptCore/dfg/DFGVariableAccessData.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVariableAccessData.h (revision 152582) >+++ Source/JavaScriptCore/dfg/DFGVariableAccessData.h (working copy) >@@ -27,6 +27,7 @@ > #define DFGVariableAccessData_h > > #include "DFGDoubleFormatState.h" >+#include "DFGFlushFormat.h" > #include "DFGNodeFlags.h" > #include "Operands.h" > #include "SpeculatedType.h" >@@ -318,6 +319,29 @@ public: > return checkAndSet(m_flags, m_flags | newFlags); > } > >+ FlushFormat flushFormat() >+ { >+ ASSERT(find() == this); >+ >+ if (!shouldUnboxIfPossible()) >+ return FlushedJSValue; >+ >+ if (shouldUseDoubleFormat()) >+ return FlushedDouble; >+ >+ SpeculatedType prediction = argumentAwarePrediction(); >+ if (isInt32Speculation(prediction)) >+ return FlushedInt32; >+ >+ if (isCellSpeculation(prediction)) >+ return FlushedCell; >+ >+ if (isBooleanSpeculation(prediction)) >+ return FlushedBoolean; >+ >+ return FlushedJSValue; >+ } >+ > private: > // This is slightly space-inefficient, since anything we're unified with > // will have the same operand and should have the same prediction. But >Index: Source/JavaScriptCore/ftl/FTLCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLCapabilities.cpp (revision 152582) >+++ Source/JavaScriptCore/ftl/FTLCapabilities.cpp (working copy) >@@ -82,6 +82,8 @@ inline bool canCompile(Node* node) > case Jump: > case ForceOSRExit: > case ForwardForceOSRExit: >+ case Phi: >+ case Upsilon: > // These are OK. > break; > case GetArrayLength: >@@ -174,6 +176,8 @@ inline bool canCompile(Node* node) > > bool canCompile(Graph& graph) > { >+ RELEASE_ASSERT(graph.m_form == SSA); >+ > for (BlockIndex blockIndex = graph.numBlocks(); blockIndex--;) { > BasicBlock* block = graph.block(blockIndex); > if (!block) >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 152582) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -33,6 +33,7 @@ > #include "FTLAbstractHeapRepository.h" > #include "FTLExitThunkGenerator.h" > #include "FTLFormattedValue.h" >+#include "FTLLoweredNodeValue.h" > #include "FTLOutput.h" > #include "FTLThunks.h" > #include "FTLValueSource.h" >@@ -61,10 +62,6 @@ public: > , m_ftlState(state) > , m_heaps(state.context) > , m_out(state.context) >- , m_localsBoolean(OperandsLike, state.graph.block(0)->variablesAtHead) >- , m_locals32(OperandsLike, state.graph.block(0)->variablesAtHead) >- , m_locals64(OperandsLike, state.graph.block(0)->variablesAtHead) >- , m_localsDouble(OperandsLike, state.graph.block(0)->variablesAtHead) > , m_valueSources(OperandsLike, state.graph.block(0)->variablesAtHead) > , m_lastSetOperand(std::numeric_limits<int>::max()) > , m_exitThunkGenerator(state) >@@ -74,6 +71,8 @@ public: > > void lower() > { >+ m_graph.m_dominators.computeIfNecessary(m_graph); >+ > m_ftlState.module = > LLVMModuleCreateWithNameInContext("jsBody", m_ftlState.context); > >@@ -85,12 +84,7 @@ public: > > m_prologue = appendBasicBlock(m_ftlState.context, m_ftlState.function); > m_out.appendTo(m_prologue); >- for (unsigned index = m_localsBoolean.size(); index--;) { >- m_localsBoolean[index] = buildAlloca(m_out.m_builder, m_out.boolean); >- m_locals32[index] = buildAlloca(m_out.m_builder, m_out.int32); >- m_locals64[index] = buildAlloca(m_out.m_builder, m_out.int64); >- m_localsDouble[index] = buildAlloca(m_out.m_builder, m_out.doubleType); >- } >+ createPhiVariables(); > > m_initialization = appendBasicBlock(m_ftlState.context, m_ftlState.function); > m_argumentChecks = appendBasicBlock(m_ftlState.context, m_ftlState.function); >@@ -104,19 +98,18 @@ public: > if (!m_highBlock) > continue; > m_blocks.add(m_highBlock, FTL_NEW_BLOCK(m_out, ("Block ", *m_highBlock))); >- addFlushedLocalOpRoots(); > } > >- closeOverFlushedLocalOps(); >- > m_out.appendTo(m_argumentChecks, lowBlock(m_graph.block(0))); > >- transferAndCheckArguments(); >+ checkArguments(); > > m_out.jump(lowBlock(m_graph.block(0))); > >- for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) >- compileBlock(blockIndex); >+ Vector<BasicBlock*> depthFirst; >+ m_graph.getBlocksInDepthFirstOrder(depthFirst); >+ for (unsigned i = 0; i < depthFirst.size(); ++i) >+ compileBlock(depthFirst[i]); > > // And now complete the initialization block. > linkOSRExitsAndCompleteInitializationBlocks(); >@@ -129,41 +122,40 @@ public: > > private: > >- void addFlushedLocalOpRoots() >+ void createPhiVariables() > { >- for (unsigned nodeIndex = m_highBlock->size(); nodeIndex--;) { >- Node* node = m_highBlock->at(nodeIndex); >- if (node->op() != Flush) >+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) > continue; >- addFlushedLocalOp(node); >- } >- } >- >- void closeOverFlushedLocalOps() >- { >- while (!m_flushedLocalOpWorklist.isEmpty()) { >- Node* node = m_flushedLocalOpWorklist.last(); >- m_flushedLocalOpWorklist.removeLast(); >- >- ASSERT(m_flushedLocalOps.contains(node)); >- >- DFG_NODE_DO_TO_CHILDREN(m_graph, node, addFlushedLocalEdge); >+ for (unsigned nodeIndex = block->size(); nodeIndex--;) { >+ Node* node = block->at(nodeIndex); >+ if (node->op() != Phi) >+ continue; >+ LType type; >+ switch (node->flags() & NodeResultMask) { >+ case NodeResultNumber: >+ type = m_out.doubleType; >+ break; >+ case NodeResultInt32: >+ type = m_out.int32; >+ break; >+ case NodeResultBoolean: >+ type = m_out.boolean; >+ break; >+ case NodeResultJS: >+ type = m_out.int64; >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ m_phis.add(node, buildAlloca(m_out.m_builder, type)); >+ } > } > } > >- void addFlushedLocalOp(Node* node) >- { >- if (m_flushedLocalOps.contains(node)) >- return; >- m_flushedLocalOps.add(node); >- m_flushedLocalOpWorklist.append(node); >- } >- void addFlushedLocalEdge(Node*, Edge edge) >- { >- addFlushedLocalOp(edge.node()); >- } >- >- void transferAndCheckArguments() >+ void checkArguments() > { > // While checking arguments, everything is in the stack. > for (unsigned i = m_valueSources.size(); i--;) >@@ -172,56 +164,54 @@ private: > m_codeOrigin = CodeOrigin(0); > m_node = 0; > >- for (int i = 0; i < m_graph.m_codeBlock->numParameters(); ++i) { >- Node* node = m_graph.m_arguments[i]; >- if (!node->shouldGenerate()) >- continue; >+ for (size_t i = m_graph.block(0)->ssa->flushFormatAtHead.size(); i--;) { >+ FlushFormat format = m_graph.block(0)->ssa->flushFormatAtHead[i]; >+ int operand = m_graph.block(0)->ssa->flushFormatAtHead.operandForIndex(i); > >- VariableAccessData* variable = node->variableAccessData(); >- // If it's captured then we'll be accessing it through loads and stores >- // anyway - there's no point in transfering it out. >- if (variable->isCaptured()) >+ if (format == DeadFlush || format == FlushedJSValue) > continue; > >- LValue jsValue = m_out.load64(addressFor(variable->local())); >+ RELEASE_ASSERT(format != FlushedDouble); >+ >+ MethodOfGettingAValueProfile profile = >+ MethodOfGettingAValueProfile::fromLazyOperand( >+ m_graph.m_profiledBlock, >+ LazyOperandValueProfileKey(0, operand)); > >- if (variable->shouldUnboxIfPossible()) { >- RELEASE_ASSERT(!variable->shouldUseDoubleFormat()); >+ LValue jsValue = m_out.load64(addressFor(operand)); >+ switch (format) { >+ case FlushedInt32: { >+ speculateBackward(BadType, jsValueValue(jsValue), profile, isNotInt32(jsValue)); >+ break; >+ } > >- SpeculatedType prediction = variable->argumentAwarePrediction(); >+ case FlushedCell: { >+ speculateBackward(BadType, jsValueValue(jsValue), profile, isNotCell(jsValue)); >+ break; >+ } > >- if (isInt32Speculation(prediction)) { >- speculateBackward(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue)); >- m_out.set(unboxInt32(jsValue), m_locals32.operand(variable->local())); >- continue; >- } >+ case FlushedBoolean: { >+ speculateBackward(BadType, jsValueValue(jsValue), profile, isNotBoolean(jsValue)); >+ break; >+ } > >- if (isCellSpeculation(prediction)) { >- speculateBackward(BadType, jsValueValue(jsValue), node, isNotCell(jsValue)); >- m_out.set(jsValue, m_locals64.operand(variable->local())); >- continue; >- } >- if (isBooleanSpeculation(prediction)) { >- speculateBackward(BadType, jsValueValue(jsValue), node, isNotBoolean(jsValue)); >- m_out.set(unboxBoolean(jsValue), m_localsBoolean.operand(variable->local())); >- continue; >- } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; > } >- >- m_out.set(jsValue, m_locals64.operand(variable->local())); > } > } > >- void compileBlock(BlockIndex blockIndex) >+ void compileBlock(BasicBlock* block) > { >- m_highBlock = m_graph.block(blockIndex); >+ m_highBlock = block; > if (!m_highBlock) > return; > > LBasicBlock lowBlock = m_blocks.get(m_highBlock); > > m_nextHighBlock = 0; >- for (BlockIndex nextBlockIndex = blockIndex + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) { >+ for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) { > m_nextHighBlock = m_graph.block(nextBlockIndex); > if (m_nextHighBlock) > break; >@@ -241,11 +231,7 @@ private: > > initializeOSRExitStateForBlock(); > >- m_int32Values.clear(); >- m_jsValueValues.clear(); >- m_booleanValues.clear(); >- m_storageValues.clear(); >- m_timeToLive.clear(); >+ m_live = block->ssa->liveAtHead; > > m_state.reset(); > m_state.beginBasicBlock(m_highBlock); >@@ -274,6 +260,12 @@ private: > m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation; > > switch (m_node->op()) { >+ case Upsilon: >+ compileUpsilon(); >+ break; >+ case Phi: >+ compilePhi(); >+ break; > case JSConstant: > compileJSConstant(); > break; >@@ -445,8 +437,8 @@ private: > if (m_node->shouldGenerate()) > DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, use); > >- if (m_node->hasResult()) >- m_timeToLive.add(m_node, m_node->adjustedRefCount()); >+ if (m_node->adjustedRefCount()) >+ m_live.add(m_node); > > if (shouldExecuteEffects) > m_state.executeEffects(nodeIndex); >@@ -454,73 +446,79 @@ private: > return true; > } > >+ void compileUpsilon() >+ { >+ LValue destination = m_phis.get(m_node->phi()); >+ >+ switch (m_node->phi()->flags() & NodeResultMask) { >+ case NodeResultNumber: >+ m_out.set(lowDouble(m_node->child1()), destination); >+ break; >+ case NodeResultInt32: >+ m_out.set(lowInt32(m_node->child1()), destination); >+ break; >+ case NodeResultBoolean: >+ m_out.set(lowBoolean(m_node->child1()), destination); >+ break; >+ case NodeResultJS: >+ m_out.set(lowJSValue(m_node->child1()), destination); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ } >+ >+ void compilePhi() >+ { >+ LValue source = m_phis.get(m_node); >+ >+ switch (m_node->flags() & NodeResultMask) { >+ case NodeResultNumber: >+ setDouble(m_out.get(source)); >+ break; >+ case NodeResultInt32: >+ setInt32(m_out.get(source)); >+ break; >+ case NodeResultBoolean: >+ setBoolean(m_out.get(source)); >+ break; >+ case NodeResultJS: >+ setJSValue(m_out.get(source)); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ } >+ > void compileJSConstant() > { > JSValue value = m_graph.valueOfJSConstant(m_node); > if (value.isDouble()) >- m_doubleValues.add(m_node, m_out.constDouble(value.asDouble())); >+ setDouble(m_out.constDouble(value.asDouble())); > else >- m_jsValueValues.add(m_node, m_out.constInt64(JSValue::encode(value))); >+ setJSValue(m_out.constInt64(JSValue::encode(value))); > } > > void compileWeakJSConstant() > { >- m_jsValueValues.add(m_node, weakPointer(m_node->weakConstant())); >+ setJSValue(weakPointer(m_node->weakConstant())); > } > > void compileGetLocal() > { >- // GetLocal is one of the few nodes that may be left behind, with !shouldGenerate(). >- if (!m_node->shouldGenerate()) >- return; >+ // GetLocals arise only in two cases: captured variables and arguments. > > VariableAccessData* variable = m_node->variableAccessData(); >- SpeculatedType prediction = variable->argumentAwarePrediction(); > AbstractValue& value = m_state.variables().operand(variable->local()); > >- if (prediction == SpecNone) { >- terminate(InadequateCoverage); >- return; >- } >- >- if (value.isClear()) { >- // FIXME: We should trap instead. >- // https://bugs.webkit.org/show_bug.cgi?id=110383 >- terminate(InadequateCoverage); >- return; >- } >- >- if (variable->isCaptured()) { >- if (isInt32Speculation(value.m_value)) >- m_int32Values.add(m_node, m_out.load32(payloadFor(variable->local()))); >- else >- m_jsValueValues.add(m_node, m_out.load64(addressFor(variable->local()))); >- return; >- } >+ RELEASE_ASSERT(!variable->shouldUseDoubleFormat()); > >- if (variable->shouldUnboxIfPossible()) { >- if (variable->shouldUseDoubleFormat()) { >- m_doubleValues.add(m_node, m_out.get(m_localsDouble.operand(variable->local()))); >- return; >- } >- >- // Locals that are marked shouldUnboxIfPossible() that aren't also forced to >- // use double format, and that have the right prediction, will always be >- // speculated on SetLocal and will always be stored into an appropriately >- // typed reference LValue. >- if (isInt32Speculation(prediction)) { >- m_int32Values.add(m_node, m_out.get(m_locals32.operand(variable->local()))); >- return; >- } >- if (isBooleanSpeculation(prediction)) { >- m_booleanValues.add(m_node, m_out.get(m_localsBoolean.operand(variable->local()))); >- return; >- } >- // We skip the Cell case here because that gets treated identically to >- // JSValues, since cells are stored untagged. >- } >- >- m_jsValueValues.add(m_node, m_out.get(m_locals64.operand(variable->local()))); >+ if (isInt32Speculation(value.m_value)) >+ setInt32(m_out.load32(payloadFor(variable->local()))); >+ else >+ setJSValue(m_out.load64(addressFor(variable->local()))); > } > > void compileSetLocal() >@@ -529,64 +527,40 @@ private: > > VariableAccessData* variable = m_node->variableAccessData(); > SpeculatedType prediction = variable->argumentAwarePrediction(); >- bool needsFlushing = m_flushedLocalOps.contains(m_node); > > if (variable->shouldUnboxIfPossible()) { > if (variable->shouldUseDoubleFormat()) { > LValue value = lowDouble(m_node->child1()); >- m_out.set(value, m_localsDouble.operand(variable->local())); >- if (needsFlushing) { >- m_out.storeDouble(value, addressFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(DoubleInJSStack); >- } else >- m_valueSources.operand(variable->local()) = ValueSource(DoubleInLocals); >+ m_out.storeDouble(value, addressFor(variable->local())); >+ m_valueSources.operand(variable->local()) = ValueSource(DoubleInJSStack); > return; > } > > if (isInt32Speculation(prediction)) { > LValue value = lowInt32(m_node->child1()); >- m_out.set(value, m_locals32.operand(variable->local())); >- if (needsFlushing) { >- m_out.store32(value, payloadFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(Int32InJSStack); >- } else >- m_valueSources.operand(variable->local()) = ValueSource(Int32InLocals); >+ m_out.store32(value, payloadFor(variable->local())); >+ m_valueSources.operand(variable->local()) = ValueSource(Int32InJSStack); > return; > } > if (isCellSpeculation(prediction)) { > LValue value = lowCell(m_node->child1()); >- m_out.set(value, m_locals64.operand(variable->local())); >- if (needsFlushing) { >- m_out.store64(value, addressFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); >- } else >- m_valueSources.operand(variable->local()) = ValueSource(ValueInLocals); >+ m_out.store64(value, addressFor(variable->local())); >+ m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); > return; > } > if (isBooleanSpeculation(prediction)) { >- m_out.set(lowBoolean(m_node->child1()), m_localsBoolean.operand(variable->local())); >- if (needsFlushing) { >- m_out.store64(lowJSValue(m_node->child1()), addressFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); >- } else >- m_valueSources.operand(variable->local()) = ValueSource(ValueInLocals); >+ speculateBoolean(m_node->child1()); >+ m_out.store64( >+ lowJSValue(m_node->child1(), ManualOperandSpeculation), >+ addressFor(variable->local())); >+ m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); > return; > } > } > > LValue value = lowJSValue(m_node->child1()); >- if (variable->isCaptured()) { >- m_out.store64(value, addressFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); >- return; >- } >- >- m_out.set(value, m_locals64.operand(variable->local())); >- if (needsFlushing) { >- m_out.store64(value, addressFor(variable->local())); >- m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); >- } else >- m_valueSources.operand(variable->local()) = ValueSource(ValueInLocals); >+ m_out.store64(value, addressFor(variable->local())); >+ m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack); > } > > void compileMovHint() >@@ -620,19 +594,18 @@ private: > LValue right = lowInt32(m_node->child2()); > > if (nodeCanTruncateInteger(m_node->arithNodeFlags())) { >- m_int32Values.add(m_node, m_out.add(left, right)); >+ setInt32(m_out.add(left, right)); > break; > } > > LValue result = m_out.addWithOverflow32(left, right); > speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); >- m_int32Values.add(m_node, m_out.extractValue(result, 0)); >+ setInt32(m_out.extractValue(result, 0)); > break; > } > > case NumberUse: { >- m_doubleValues.add( >- m_node, >+ setDouble( > m_out.doubleAdd(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > break; > } >@@ -651,19 +624,18 @@ private: > LValue right = lowInt32(m_node->child2()); > > if (nodeCanTruncateInteger(m_node->arithNodeFlags())) { >- m_int32Values.add(m_node, m_out.sub(left, right)); >+ setInt32(m_out.sub(left, right)); > break; > } > > LValue result = m_out.subWithOverflow32(left, right); > speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); >- m_int32Values.add(m_node, m_out.extractValue(result, 0)); >+ setInt32(m_out.extractValue(result, 0)); > break; > } > > case NumberUse: { >- m_doubleValues.add( >- m_node, >+ setDouble( > m_out.doubleSub(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > break; > } >@@ -703,13 +675,12 @@ private: > m_out.appendTo(continuation, lastNext); > } > >- m_int32Values.add(m_node, result); >+ setInt32(result); > break; > } > > case NumberUse: { >- m_doubleValues.add( >- m_node, >+ setDouble( > m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > break; > } >@@ -800,13 +771,12 @@ private: > > m_out.appendTo(done, lastNext); > >- m_int32Values.add(m_node, m_out.phi(m_out.int32, results)); >+ setInt32(m_out.phi(m_out.int32, results)); > break; > } > > case NumberUse: { >- m_doubleValues.add( >- m_node, >+ setDouble( > m_out.doubleDiv(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > break; > } >@@ -891,13 +861,12 @@ private: > > m_out.appendTo(done, lastNext); > >- m_int32Values.add(m_node, m_out.phi(m_out.int32, results)); >+ setInt32(m_out.phi(m_out.int32, results)); > break; > } > > case NumberUse: { >- m_doubleValues.add( >- m_node, >+ setDouble( > m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > break; > } >@@ -915,8 +884,7 @@ private: > LValue left = lowInt32(m_node->child1()); > LValue right = lowInt32(m_node->child2()); > >- m_int32Values.add( >- m_node, >+ setInt32( > m_out.select( > m_node->op() == ArithMin > ? m_out.lessThan(left, right) >@@ -950,7 +918,7 @@ private: > m_out.jump(continuation); > > m_out.appendTo(continuation, lastNext); >- m_doubleValues.add(m_node, m_out.phi(m_out.doubleType, results)); >+ setDouble(m_out.phi(m_out.doubleType, results)); > break; > } > >@@ -971,12 +939,12 @@ private: > > speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31))); > >- m_int32Values.add(m_node, result); >+ setInt32(result); > break; > } > > case NumberUse: { >- m_doubleValues.add(m_node, m_out.doubleAbs(lowDouble(m_node->child1()))); >+ setDouble(m_out.doubleAbs(lowDouble(m_node->child1()))); > break; > } > >@@ -1003,12 +971,12 @@ private: > result = m_out.extractValue(overflowResult, 0); > } > >- m_int32Values.add(m_node, result); >+ setInt32(result); > break; > } > > case NumberUse: { >- m_doubleValues.add(m_node, m_out.doubleNeg(lowDouble(m_node->child1()))); >+ setDouble(m_out.doubleNeg(lowDouble(m_node->child1()))); > break; > } > >@@ -1020,47 +988,38 @@ private: > > void compileBitAnd() > { >- m_int32Values.add( >- m_node, m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); >+ setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > } > > void compileBitOr() > { >- m_int32Values.add( >- m_node, m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); >+ setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > } > > void compileBitXor() > { >- m_int32Values.add( >- m_node, m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); >+ setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > } > > void compileBitRShift() > { >- m_int32Values.add( >- m_node, >- m_out.aShr( >- lowInt32(m_node->child1()), >- m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); >+ setInt32(m_out.aShr( >+ lowInt32(m_node->child1()), >+ m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); > } > > void compileBitLShift() > { >- m_int32Values.add( >- m_node, >- m_out.shl( >- lowInt32(m_node->child1()), >- m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); >+ setInt32(m_out.shl( >+ lowInt32(m_node->child1()), >+ m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); > } > > void compileBitURShift() > { >- m_int32Values.add( >- m_node, >- m_out.lShr( >- lowInt32(m_node->child1()), >- m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); >+ setInt32(m_out.lShr( >+ lowInt32(m_node->child1()), >+ m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); > } > > void compileUInt32ToNumber() >@@ -1068,14 +1027,14 @@ private: > LValue value = lowInt32(m_node->child1()); > > if (!nodeCanSpeculateInteger(m_node->arithNodeFlags())) { >- m_doubleValues.add(m_node, m_out.unsignedToDouble(value)); >+ setDouble(m_out.unsignedToDouble(value)); > return; > } > > speculateForward( > Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero), > FormattedValue(ValueFormatUInt32, value)); >- m_int32Values.add(m_node, value); >+ setInt32(value); > } > > void compileInt32ToDouble() >@@ -1087,7 +1046,7 @@ private: > // contemporaneous low-level representations. So, this gives child1 a double > // representation and then forwards that representation to m_node. > >- m_doubleValues.add(m_node, lowDouble(m_node->child1())); >+ setDouble(lowDouble(m_node->child1())); > } > > void compileCheckStructure() >@@ -1215,8 +1174,7 @@ private: > > void compileGetButterfly() > { >- m_storageValues.add( >- m_node, m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly)); >+ setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly)); > } > > void compileGetArrayLength() >@@ -1225,8 +1183,7 @@ private: > case Array::Int32: > case Array::Double: > case Array::Contiguous: { >- m_int32Values.add( >- m_node, m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength)); >+ setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength)); > break; > } > >@@ -1256,7 +1213,7 @@ private: > storage, m_out.zeroExt(index, m_out.intPtr), > m_state.forNode(m_node->child2()).m_value)); > speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result)); >- m_jsValueValues.add(m_node, result); >+ setJSValue(result); > return; > } > >@@ -1288,7 +1245,7 @@ private: > LoadFromHole, noValue(), 0, > m_out.doubleNotEqualOrUnordered(result, result)); > } >- m_doubleValues.add(m_node, result); >+ setDouble(result); > break; > } > >@@ -1388,8 +1345,7 @@ private: > StorageAccessData& data = > m_graph.m_storageAccessData[m_node->storageAccessDataIndex()]; > >- m_jsValueValues.add( >- m_node, >+ setJSValue( > m_out.load64( > m_out.address( > m_heaps.properties[data.identifierNumber], >@@ -1412,7 +1368,7 @@ private: > > void compileGetGlobalVar() > { >- m_jsValueValues.add(m_node, m_out.load64(m_out.absolute(m_node->registerPointer()))); >+ setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer()))); > } > > void compilePutGlobalVar() >@@ -1437,30 +1393,27 @@ private: > { > ASSERT(m_graph.valueOfJSConstant(m_node->child2().node()).isNull()); > masqueradesAsUndefinedWatchpointIfIsStillValid(); >- m_booleanValues.add( >- m_node, equalNullOrUndefined( >+ setBoolean( >+ equalNullOrUndefined( > m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined)); > } > > void compileCompareStrictEq() > { > if (m_node->isBinaryUseKind(Int32Use)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > return; > } > > if (m_node->isBinaryUseKind(NumberUse)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > } > > if (m_node->isBinaryUseKind(ObjectUse)) { > masqueradesAsUndefinedWatchpointIfIsStillValid(); >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.equal( > lowNonNullObject(m_node->child1()), > lowNonNullObject(m_node->child2()))); >@@ -1477,19 +1430,16 @@ private: > if (constant.isUndefinedOrNull() > && !masqueradesAsUndefinedWatchpointIfIsStillValid()) { > if (constant.isNull()) { >- m_booleanValues.add( >- m_node, equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNull)); >+ setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNull)); > return; > } > > ASSERT(constant.isUndefined()); >- m_booleanValues.add( >- m_node, equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined)); >+ setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined)); > return; > } > >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.equal( > lowJSValue(m_node->child1()), > m_out.constInt64(JSValue::encode(constant)))); >@@ -1498,15 +1448,13 @@ private: > void compileCompareLess() > { > if (m_node->isBinaryUseKind(Int32Use)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.lessThan(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > return; > } > > if (m_node->isBinaryUseKind(NumberUse)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > return; > } >@@ -1517,15 +1465,13 @@ private: > void compileCompareLessEq() > { > if (m_node->isBinaryUseKind(Int32Use)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > return; > } > > if (m_node->isBinaryUseKind(NumberUse)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.doubleLessThanOrEqual( > lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > return; >@@ -1537,15 +1483,13 @@ private: > void compileCompareGreater() > { > if (m_node->isBinaryUseKind(Int32Use)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.greaterThan(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > return; > } > > if (m_node->isBinaryUseKind(NumberUse)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.doubleGreaterThan( > lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > return; >@@ -1557,16 +1501,14 @@ private: > void compileCompareGreaterEq() > { > if (m_node->isBinaryUseKind(Int32Use)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.greaterThanOrEqual( > lowInt32(m_node->child1()), lowInt32(m_node->child2()))); > return; > } > > if (m_node->isBinaryUseKind(NumberUse)) { >- m_booleanValues.add( >- m_node, >+ setBoolean( > m_out.doubleGreaterThanOrEqual( > lowDouble(m_node->child1()), lowDouble(m_node->child2()))); > return; >@@ -1577,7 +1519,7 @@ private: > > void compileLogicalNot() > { >- m_booleanValues.add(m_node, m_out.bitNot(boolify(m_node->child1()))); >+ setBoolean(m_out.bitNot(boolify(m_node->child1()))); > } > > void compileJump() >@@ -1931,6 +1873,14 @@ private: > } > > void speculateBackward( >+ ExitKind kind, FormattedValue lowValue, MethodOfGettingAValueProfile profile, >+ LValue failCondition) >+ { >+ appendOSRExit( >+ kind, lowValue, profile, failCondition, BackwardSpeculation, FormattedValue()); >+ } >+ >+ void speculateBackward( > ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) > { > appendOSRExit( >@@ -1999,14 +1949,17 @@ private: > { > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use)); > >- if (LValue result = m_int32Values.get(edge.node())) >- return result; >- >- if (LValue boxedResult = m_jsValueValues.get(edge.node())) { >+ LoweredNodeValue value = m_int32Values.get(edge.node()); >+ if (isValid(value)) >+ return value.value(); >+ >+ value = m_jsValueValues.get(edge.node()); >+ if (isValid(value)) { >+ LValue boxedResult = value.value(); > FTL_TYPE_CHECK( > jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult)); > LValue result = unboxInt32(boxedResult); >- m_int32Values.add(edge.node(), result); >+ setInt32(edge.node(), result); > return result; > } > >@@ -2019,10 +1972,12 @@ private: > { > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind())); > >- if (LValue uncheckedResult = m_jsValueValues.get(edge.node())) { >+ LoweredNodeValue value = m_jsValueValues.get(edge.node()); >+ if (isValid(value)) { >+ LValue uncheckedValue = value.value(); > FTL_TYPE_CHECK( >- jsValueValue(uncheckedResult), edge, SpecCell, isNotCell(uncheckedResult)); >- return uncheckedResult; >+ jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue)); >+ return uncheckedValue; > } > > RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecCell)); >@@ -2061,14 +2016,17 @@ private: > { > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse); > >- if (LValue result = m_booleanValues.get(edge.node())) >- return result; >- >- if (LValue unboxedResult = m_jsValueValues.get(edge.node())) { >+ LoweredNodeValue value = m_booleanValues.get(edge.node()); >+ if (isValid(value)) >+ return value.value(); >+ >+ value = m_jsValueValues.get(edge.node()); >+ if (isValid(value)) { >+ LValue unboxedResult = value.value(); > FTL_TYPE_CHECK( > jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult)); > LValue result = unboxBoolean(unboxedResult); >- m_booleanValues.add(edge.node(), result); >+ setBoolean(edge.node(), result); > return result; > } > >@@ -2081,16 +2039,21 @@ private: > { > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind())); > >- if (LValue result = m_doubleValues.get(edge.node())) >- return result; >- >- if (LValue intResult = m_int32Values.get(edge.node())) { >- LValue result = m_out.intToDouble(intResult); >- m_doubleValues.add(edge.node(), result); >+ 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; > } > >- if (LValue boxedResult = m_jsValueValues.get(edge.node())) { >+ 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")); >@@ -2115,7 +2078,7 @@ private: > > LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble); > >- m_doubleValues.add(edge.node(), result); >+ setDouble(edge.node(), result); > return result; > } > >@@ -2128,24 +2091,28 @@ private: > { > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse); > >- if (LValue result = m_jsValueValues.get(edge.node())) >- return result; >- >- if (LValue unboxedResult = m_int32Values.get(edge.node())) { >- LValue result = boxInt32(unboxedResult); >- m_jsValueValues.add(edge.node(), result); >+ LoweredNodeValue value = m_jsValueValues.get(edge.node()); >+ if (isValid(value)) >+ return value.value(); >+ >+ value = m_int32Values.get(edge.node()); >+ if (isValid(value)) { >+ LValue result = boxInt32(value.value()); >+ setJSValue(edge.node(), result); > return result; > } > >- if (LValue unboxedResult = m_booleanValues.get(edge.node())) { >- LValue result = boxBoolean(unboxedResult); >- m_jsValueValues.add(edge.node(), result); >+ value = m_booleanValues.get(edge.node()); >+ if (isValid(value)) { >+ LValue result = boxBoolean(value.value()); >+ setJSValue(edge.node(), result); > return result; > } > >- if (LValue unboxedResult = m_doubleValues.get(edge.node())) { >- LValue result = boxDouble(unboxedResult); >- m_jsValueValues.add(edge.node(), result); >+ value = m_doubleValues.get(edge.node()); >+ if (isValid(value)) { >+ LValue result = boxDouble(value.value()); >+ setJSValue(edge.node(), result); > return result; > } > >@@ -2155,11 +2122,12 @@ private: > > LValue lowStorage(Edge edge) > { >- if (LValue result = m_storageValues.get(edge.node())) >- return result; >+ LoweredNodeValue value = m_storageValues.get(edge.node()); >+ if (isValid(value)) >+ return value.value(); > > LValue result = lowCell(edge); >- m_storageValues.add(edge.node(), result); >+ setStorage(edge.node(), result); > return result; > } > >@@ -2242,6 +2210,9 @@ private: > case NumberUse: > speculateNumber(edge); > break; >+ case BooleanUse: >+ speculateBoolean(edge); >+ break; > default: > RELEASE_ASSERT_NOT_REACHED(); > } >@@ -2342,6 +2313,11 @@ private: > doubleValue(value), edge, SpecRealNumber, > m_out.doubleNotEqualOrUnordered(value, value)); > } >+ >+ void speculateBoolean(Edge edge) >+ { >+ lowBoolean(edge); >+ } > > bool masqueradesAsUndefinedWatchpointIsStillValid() > { >@@ -2430,22 +2406,15 @@ private: > > bool isLive(Node* node) > { >- HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(node); >- ASSERT(iter != m_timeToLive.end()); >- return !!iter->value; >+ return m_live.contains(node); > } > > void use(Edge edge) > { >- if (!edge->hasResult()) { >- ASSERT(edge->hasVariableAccessData()); >+ ASSERT(edge->hasResult()); >+ if (!edge.doesKill()) > return; >- } >- >- HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(edge.node()); >- ASSERT(iter != m_timeToLive.end()); >- ASSERT(iter->value); >- iter->value--; >+ m_live.remove(edge.node()); > } > > // Wrapper used only for DFG_NODE_DO_TO_CHILDREN >@@ -2462,63 +2431,34 @@ private: > void initializeOSRExitStateForBlock() > { > for (unsigned i = m_valueSources.size(); i--;) { >- Node* node = m_highBlock->variablesAtHead[i]; >- if (!node) { >- m_valueSources[i] = ValueSource(SourceIsDead); >- continue; >- } >- >- VariableAccessData* variable = node->variableAccessData(); >- SpeculatedType prediction = variable->argumentAwarePrediction(); >- >- if (variable->isArgumentsAlias()) { >- m_valueSources[i] = ValueSource(ArgumentsSource); >- continue; >- } >- >- if (!node->shouldGenerate()) { >- m_valueSources[i] = ValueSource(SourceIsDead); >- continue; >- } >- >- if (m_flushedLocalOps.contains(node)) { >- // This value will have been flushed to the JSStack in some form or >- // another. >- >- if (variable->shouldUnboxIfPossible()) { >- if (variable->shouldUseDoubleFormat()) { >- m_valueSources[i] = ValueSource(DoubleInJSStack); >- continue; >- } >- >- if (isInt32Speculation(prediction)) { >- m_valueSources[i] = ValueSource(Int32InJSStack); >- continue; >- } >+ FlushFormat format = m_highBlock->ssa->flushFormatAtHead[i]; >+ switch (format) { >+ case DeadFlush: { >+ // Must consider available nodes instead. >+ Node* node = m_highBlock->ssa->availabilityAtHead[i]; >+ if (!node) { >+ m_valueSources[i] = ValueSource(SourceIsDead); >+ break; > } > >- m_valueSources[i] = ValueSource(ValueInJSStack); >- continue; >+ m_valueSources[i] = ValueSource(node); >+ break; > } >- >- if (variable->shouldUnboxIfPossible()) { >- if (variable->shouldUseDoubleFormat()) { >- m_valueSources[i] = ValueSource(DoubleInLocals); >- continue; >- } > >- if (isInt32Speculation(prediction)) { >- m_valueSources[i] = ValueSource(Int32InLocals); >- continue; >- } >+ case FlushedInt32: >+ m_valueSources[i] = ValueSource(Int32InJSStack); >+ break; > >- if (isBooleanSpeculation(prediction)) { >- m_valueSources[i] = ValueSource(BooleanInLocals); >- continue; >- } >+ case FlushedDouble: >+ m_valueSources[i] = ValueSource(DoubleInJSStack); >+ break; >+ >+ case FlushedCell: >+ case FlushedBoolean: >+ case FlushedJSValue: >+ m_valueSources[i] = ValueSource(ValueInJSStack); >+ break; > } >- >- m_valueSources[i] = ValueSource(ValueInLocals); > } > } > >@@ -2526,6 +2466,15 @@ private: > ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition, > SpeculationDirection direction, FormattedValue recovery) > { >+ appendOSRExit( >+ kind, lowValue, m_graph.methodOfGettingAValueProfileFor(highValue), >+ failCondition, direction, recovery); >+ } >+ >+ void appendOSRExit( >+ ExitKind kind, FormattedValue lowValue, MethodOfGettingAValueProfile profile, >+ LValue failCondition, SpeculationDirection direction, FormattedValue recovery) >+ { > if (Options::ftlTrapsOnOSRExit()) { > LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase")); > LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation")); >@@ -2546,11 +2495,9 @@ private: > ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.osrExit.size()); > unsigned index = m_ftlState.osrExit.size(); > >- m_ftlState.jitCode->osrExit.append( >- OSRExit( >- kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue), >- m_codeOrigin, m_lastSetOperand, m_valueSources.numberOfArguments(), >- m_valueSources.numberOfLocals())); >+ m_ftlState.jitCode->osrExit.append(OSRExit( >+ kind, lowValue.format(), profile, m_codeOrigin, m_lastSetOperand, >+ m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals())); > m_ftlState.osrExit.append(OSRExitCompilationInfo()); > > OSRExit& exit = m_ftlState.jitCode->osrExit.last(); >@@ -2602,27 +2549,6 @@ private: > case DoubleInJSStack: > exit.m_values[i] = ExitValue::inJSStackAsDouble(); > break; >- case ValueInLocals: >- addExitArgument( >- exit, arguments, i, ValueFormatJSValue, m_out.get(m_locals64[i])); >- break; >- case Int32InLocals: >- addExitArgument( >- exit, arguments, i, ValueFormatInt32, m_out.get(m_locals32[i])); >- break; >- case BooleanInLocals: >- addExitArgument( >- exit, arguments, i, ValueFormatBoolean, m_out.get(m_localsBoolean[i])); >- break; >- case DoubleInLocals: >- addExitArgument( >- exit, arguments, i, ValueFormatDouble, m_out.get(m_localsDouble[i])); >- break; >- case ArgumentsSource: >- // FIXME: implement PhantomArguments. >- // https://bugs.webkit.org/show_bug.cgi?id=113986 >- RELEASE_ASSERT_NOT_REACHED(); >- break; > case SourceIsDead: > exit.m_values[i] = ExitValue::dead(); > break; >@@ -2682,12 +2608,10 @@ private: > Node* uint32ToNumber = 0; > Node* doubleAsInt32 = 0; > >- HashMap<Node*, unsigned>::iterator iter = m_timeToLive.begin(); >- HashMap<Node*, unsigned>::iterator end = m_timeToLive.end(); >+ HashSet<Node*>::iterator iter = m_live.begin(); >+ HashSet<Node*>::iterator end = m_live.end(); > for (; iter != end; ++iter) { >- if (!iter->value) >- continue; >- Node* candidate = iter->key; >+ Node* candidate = *iter; > if (!candidate->child1()) > continue; > if (candidate->child1() != node) >@@ -2732,24 +2656,28 @@ private: > } > > ASSERT(isLive(node)); >- >- if (LValue result = m_int32Values.get(node)) { >- addExitArgument(exit, arguments, index, ValueFormatInt32, result); >+ >+ LoweredNodeValue value = m_int32Values.get(node); >+ if (isValid(value)) { >+ addExitArgument(exit, arguments, index, ValueFormatInt32, value.value()); > return; > } > >- if (LValue result = m_booleanValues.get(node)) { >- addExitArgument(exit, arguments, index, ValueFormatBoolean, result); >+ value = m_booleanValues.get(node); >+ if (isValid(value)) { >+ addExitArgument(exit, arguments, index, ValueFormatBoolean, value.value()); > return; > } > >- if (LValue result = m_jsValueValues.get(node)) { >- addExitArgument(exit, arguments, index, ValueFormatJSValue, result); >+ value = m_jsValueValues.get(node); >+ if (isValid(value)) { >+ addExitArgument(exit, arguments, index, ValueFormatJSValue, value.value()); > return; > } > >- if (LValue result = m_doubleValues.get(node)) { >- addExitArgument(exit, arguments, index, ValueFormatDouble, result); >+ value = m_doubleValues.get(node); >+ if (isValid(value)) { >+ addExitArgument(exit, arguments, index, ValueFormatDouble, value.value()); > return; > } > >@@ -2834,6 +2762,57 @@ private: > m_valueSources.operand(operand) = ValueSource(node->child1().node()); > } > >+ void setInt32(Node* node, LValue value) >+ { >+ m_int32Values.set(node, LoweredNodeValue(value, m_highBlock)); >+ } >+ void setJSValue(Node* node, LValue value) >+ { >+ m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock)); >+ } >+ void setBoolean(Node* node, LValue value) >+ { >+ m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock)); >+ } >+ void setStorage(Node* node, LValue value) >+ { >+ m_storageValues.set(node, LoweredNodeValue(value, m_highBlock)); >+ } >+ void setDouble(Node* node, LValue value) >+ { >+ m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock)); >+ } >+ >+ void setInt32(LValue value) >+ { >+ setInt32(m_node, value); >+ } >+ void setJSValue(LValue value) >+ { >+ setJSValue(m_node, value); >+ } >+ void setBoolean(LValue value) >+ { >+ setBoolean(m_node, value); >+ } >+ void setStorage(LValue value) >+ { >+ setStorage(m_node, value); >+ } >+ void setDouble(LValue value) >+ { >+ setDouble(m_node, value); >+ } >+ >+ bool isValid(const LoweredNodeValue& value) >+ { >+ if (!value) >+ return false; >+ if (!m_graph.m_dominators.dominates(m_highBlock, value.block())) >+ return false; >+ return true; >+ } >+ > void addWeakReference(JSCell* target) > { > m_ftlState.jitCode->common.weakReferences.append( >@@ -2888,20 +2867,14 @@ private: > LValue m_tagTypeNumber; > LValue m_tagMask; > >- HashSet<Node*> m_flushedLocalOps; >- Vector<Node*> m_flushedLocalOpWorklist; >+ HashMap<Node*, LoweredNodeValue> m_int32Values; >+ HashMap<Node*, LoweredNodeValue> m_jsValueValues; >+ HashMap<Node*, LoweredNodeValue> m_booleanValues; >+ HashMap<Node*, LoweredNodeValue> m_storageValues; >+ HashMap<Node*, LoweredNodeValue> m_doubleValues; >+ HashSet<Node*> m_live; > >- HashMap<Node*, LValue> m_int32Values; >- HashMap<Node*, LValue> m_jsValueValues; >- HashMap<Node*, LValue> m_booleanValues; >- HashMap<Node*, LValue> m_storageValues; >- HashMap<Node*, LValue> m_doubleValues; >- HashMap<Node*, unsigned> m_timeToLive; >- >- Operands<LValue> m_localsBoolean; >- Operands<LValue> m_locals32; >- Operands<LValue> m_locals64; >- Operands<LValue> m_localsDouble; >+ HashMap<Node*, LValue> m_phis; > > Operands<ValueSource> m_valueSources; > int m_lastSetOperand; >Index: Source/JavaScriptCore/ftl/FTLLoweredNodeValue.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLoweredNodeValue.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLLoweredNodeValue.h (working copy) >@@ -0,0 +1,78 @@ >+/* >+ * 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 FTLLoweredNodeValue_h >+#define FTLLoweredNodeValue_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGBasicBlock.h" >+#include "FTLAbbreviatedTypes.h" >+ >+namespace JSC { namespace FTL { >+ >+// Represents the act of having lowered a DFG::Node to an LValue, and records the >+// DFG::BasicBlock that did the lowering. The LValue is what we use most often, but >+// we need to verify that we're in a block that is dominated by the one that did >+// the lowering. We're guaranteed that for each DFG::Node, there will be one >+// LoweredNodeValue that always dominates all uses of the DFG::Node; but there may >+// be others that don't dominate and we're effectively doing opportunistic GVN on >+// the lowering code. >+ >+class LoweredNodeValue { >+public: >+ LoweredNodeValue() >+ : m_value(0) >+ , m_block(0) >+ { >+ } >+ >+ LoweredNodeValue(LValue value, DFG::BasicBlock* block) >+ : m_value(value) >+ , m_block(block) >+ { >+ ASSERT(m_value); >+ ASSERT(m_block); >+ } >+ >+ bool isSet() const { return !!m_value; } >+ bool operator!() const { return !isSet(); } >+ >+ LValue value() const { return m_value; } >+ DFG::BasicBlock* block() const { return m_block; } >+ >+private: >+ LValue m_value; >+ DFG::BasicBlock* m_block; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLLoweredNodeValue_h >+ >Index: Source/JavaScriptCore/ftl/FTLValueFromBlock.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueFromBlock.h (revision 152582) >+++ Source/JavaScriptCore/ftl/FTLValueFromBlock.h (working copy) >@@ -36,6 +36,12 @@ namespace JSC { namespace FTL { > > class ValueFromBlock { > public: >+ ValueFromBlock() >+ : m_value(0) >+ , m_block(0) >+ { >+ } >+ > ValueFromBlock(LValue value, LBasicBlock block) > : m_value(value) > , m_block(block) >Index: Source/JavaScriptCore/ftl/FTLValueSource.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueSource.cpp (revision 152582) >+++ Source/JavaScriptCore/ftl/FTLValueSource.cpp (working copy) >@@ -45,21 +45,6 @@ void ValueSource::dump(PrintStream& out) > case DoubleInJSStack: > out.print("DoubleInJSStack"); > return; >- case ValueInLocals: >- out.print("ValueInLocals"); >- return; >- case Int32InLocals: >- out.print("Int32InLocals"); >- return; >- case BooleanInLocals: >- out.print("BooleanInLocals"); >- return; >- case DoubleInLocals: >- out.print("DoubleInLocals"); >- return; >- case ArgumentsSource: >- out.print("ArgumentsSource"); >- return; > case SourceIsDead: > out.print("SourceIsDead"); > return; >Index: Source/JavaScriptCore/ftl/FTLValueSource.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueSource.h (revision 152582) >+++ Source/JavaScriptCore/ftl/FTLValueSource.h (working copy) >@@ -41,11 +41,6 @@ enum ValueSourceKind { > ValueInJSStack, > Int32InJSStack, > DoubleInJSStack, >- ValueInLocals, >- Int32InLocals, >- BooleanInLocals, >- DoubleInLocals, >- ArgumentsSource, > SourceIsDead, > HaveNode > }; >Index: Source/WTF/ChangeLog >=================================================================== >--- Source/WTF/ChangeLog (revision 152582) >+++ Source/WTF/ChangeLog (working copy) >@@ -1,3 +1,28 @@ >+2013-07-11 Filip Pizlo <fpizlo@apple.com> >+ >+ Need a short description (OOPS!). >+ Need the bug URL (OOPS!). >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WTF.xcodeproj/project.pbxproj: >+ * wtf/HashSet.h: >+ (HashSet): >+ (WTF): >+ (WTF::::add): >+ (WTF::=): >+ * wtf/HashTable.h: >+ (WTF::::HashTable): >+ (WTF::=): >+ * wtf/Insertion.h: Added. >+ (WTF): >+ (Insertion): >+ (WTF::Insertion::Insertion): >+ (WTF::Insertion::index): >+ (WTF::Insertion::element): >+ (WTF::Insertion::operator<): >+ (WTF::executeInsertions): >+ > 2013-07-02 Filip Pizlo <fpizlo@apple.com> > > Unreviewed, fix 32-bit build. >Index: Source/WTF/WTF.xcodeproj/project.pbxproj >=================================================================== >--- Source/WTF/WTF.xcodeproj/project.pbxproj (revision 152582) >+++ Source/WTF/WTF.xcodeproj/project.pbxproj (working copy) >@@ -36,6 +36,8 @@ > 0FD81AC5154FB22E00983E72 /* FastBitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD81AC4154FB22E00983E72 /* FastBitVector.h */; settings = {ATTRIBUTES = (); }; }; > 0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */; }; > 0FDDBFA81666DFA300C55FEF /* StringPrintStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */; }; >+ 0FE505571787A80600B35F8C /* Insertion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE505561787A80200B35F8C /* Insertion.h */; }; >+ 0FE5057F179089FE00B35F8C /* ListDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE5057E179089F900B35F8C /* ListDump.h */; }; > 143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; }; > 143F61201565F0F900DB514A /* RAMSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 143F611E1565F0F900DB514A /* RAMSize.h */; settings = {ATTRIBUTES = (); }; }; > 1469419216EAAF6D0024E146 /* RunLoopTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1469419016EAAF6D0024E146 /* RunLoopTimer.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -352,6 +354,8 @@ > 0FD81AC4154FB22E00983E72 /* FastBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastBitVector.h; sourceTree = "<group>"; }; > 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringPrintStream.cpp; sourceTree = "<group>"; }; > 0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringPrintStream.h; sourceTree = "<group>"; }; >+ 0FE505561787A80200B35F8C /* Insertion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Insertion.h; sourceTree = "<group>"; }; >+ 0FE5057E179089F900B35F8C /* ListDump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ListDump.h; sourceTree = "<group>"; }; > 0FEC3EE4171B834700FDAC8D /* ByteSpinLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ByteSpinLock.h; sourceTree = "<group>"; }; > 143F611D1565F0F900DB514A /* RAMSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RAMSize.cpp; sourceTree = "<group>"; }; > 143F611E1565F0F900DB514A /* RAMSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAMSize.h; sourceTree = "<group>"; }; >@@ -785,11 +789,13 @@ > A8A472BA151A825A004123FF /* HashTraits.h */, > A8A472BB151A825A004123FF /* HexNumber.h */, > A8A472BC151A825A004123FF /* InlineASM.h */, >+ 0FE505561787A80200B35F8C /* Insertion.h */, > A8A472BE151A825A004123FF /* Int16Array.h */, > A8A472BF151A825A004123FF /* Int32Array.h */, > A8A472BD151A825A004123FF /* Int8Array.h */, > A8A472C0151A825A004123FF /* IntegralTypedArrayBase.h */, > 0F46E6DD177CBA6A00E1F755 /* LLVMHeaders.h */, >+ 0FE5057E179089F900B35F8C /* ListDump.h */, > A8A472C1151A825A004123FF /* ListHashSet.h */, > A8A472C2151A825A004123FF /* ListRefPtr.h */, > A8A472C3151A825A004123FF /* Locker.h */, >@@ -1181,6 +1187,7 @@ > A8A473E8151A825B004123FF /* MathExtras.h in Headers */, > A8A473EA151A825B004123FF /* MD5.h in Headers */, > CD5497AD15857D0300B5BC30 /* MediaTime.h in Headers */, >+ 0FE505571787A80600B35F8C /* Insertion.h in Headers */, > 4F1D115415FF11BE0026E908 /* MemoryInstrumentation.h in Headers */, > 4FD8554716133E0E00C5B704 /* MemoryInstrumentationArrayBufferView.h in Headers */, > F3FBC71E161AF7BF00BB4BD4 /* MemoryInstrumentationHashCountedSet.h in Headers */, >@@ -1308,6 +1315,7 @@ > 974CFC8E16A4F327006D5404 /* WeakPtr.h in Headers */, > A8A47446151A825B004123FF /* WTFString.h in Headers */, > A8A47487151A825B004123FF /* WTFThreadData.h in Headers */, >+ 0FE5057F179089FE00B35F8C /* ListDump.h in Headers */, > 0FC4488316FE9FE100844BE9 /* ProcessID.h in Headers */, > 0F46E6DE177CBA6A00E1F755 /* LLVMHeaders.h in Headers */, > ); >Index: Source/WTF/wtf/DataLog.h >=================================================================== >--- Source/WTF/wtf/DataLog.h (revision 152582) >+++ Source/WTF/wtf/DataLog.h (working copy) >@@ -118,6 +118,18 @@ void dataLog(const T1& value1, const T2& > dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12, value13); > } > >+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14> >+void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13, const T14& value14) >+{ >+ dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12, value13, value14); >+} >+ >+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> >+void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13, const T14& value14, const T15& value15) >+{ >+ dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12, value13, value14, value15); >+} >+ > } // namespace WTF > > using WTF::dataLog; >Index: Source/WTF/wtf/HashSet.h >=================================================================== >--- Source/WTF/wtf/HashSet.h (revision 152582) >+++ Source/WTF/wtf/HashSet.h (working copy) >@@ -86,12 +86,19 @@ namespace WTF { > // FIXME: We should reverse the order of the template arguments so that callers > // can just pass the translator and let the compiler deduce T. > template<typename T, typename HashTranslator> AddResult add(const T&); >+ >+ // Attempts to add a list of things to the set. Returns true if any of >+ // them are new to the set. Returns false if the set is unchanged. >+ template<typename IteratorType> >+ bool add(IteratorType begin, IteratorType end); > > void remove(const ValueType&); > void remove(iterator); > void clear(); > > static bool isValidValue(const ValueType&); >+ >+ bool operator==(const HashSet&) const; > > private: > friend void deleteAllValues<>(const HashSet&); >@@ -191,6 +198,16 @@ namespace WTF { > } > > template<typename T, typename U, typename V> >+ template<typename IteratorType> >+ inline bool HashSet<T, U, V>::add(IteratorType begin, IteratorType end) >+ { >+ bool changed = false; >+ for (IteratorType iter = begin; iter != end; ++iter) >+ changed |= add(*iter).isNewEntry; >+ return changed; >+ } >+ >+ template<typename T, typename U, typename V> > inline void HashSet<T, U, V>::remove(iterator it) > { > if (it.m_impl == m_impl.end()) >@@ -256,6 +273,18 @@ namespace WTF { > vector[i] = *it; > } > >+ template<typename T, typename U, typename V> >+ inline bool HashSet<T, U, V>::operator==(const HashSet& other) const >+ { >+ if (size() != other.size()) >+ return false; >+ for (const_iterator iter = begin(); iter != end(); ++iter) { >+ if (!other.contains(*iter)) >+ return false; >+ } >+ return true; >+ } >+ > } // namespace WTF > > using WTF::HashSet; >Index: Source/WTF/wtf/HashTable.h >=================================================================== >--- Source/WTF/wtf/HashTable.h (revision 152582) >+++ Source/WTF/wtf/HashTable.h (working copy) >@@ -1170,6 +1170,8 @@ namespace WTF { > { > // Copy the hash table the dumb way, by adding each element to the new table. > // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed. >+ // FIXME: It's likely that this can be improved, for static analyses that use >+ // HashSets. https://bugs.webkit.org/show_bug.cgi?id=118455 > const_iterator end = other.end(); > for (const_iterator it = other.begin(); it != end; ++it) > add(*it); >@@ -1209,6 +1211,8 @@ namespace WTF { > template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> > HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other) > { >+ // FIXME: It's likely that this can be improved, for static analyses that use >+ // HashSets. https://bugs.webkit.org/show_bug.cgi?id=118455 > HashTable tmp(other); > swap(tmp); > return *this; >Index: Source/WTF/wtf/Insertion.h >=================================================================== >--- Source/WTF/wtf/Insertion.h (revision 0) >+++ Source/WTF/wtf/Insertion.h (working copy) >@@ -0,0 +1,78 @@ >+/* >+ * 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 Insertion_h >+#define Insertion_h >+ >+namespace WTF { >+ >+template<typename T> >+class Insertion { >+public: >+ Insertion() { } >+ >+ Insertion(size_t index, T element) >+ : m_index(index) >+ , m_element(element) >+ { >+ } >+ >+ size_t index() const { return m_index; } >+ T element() const { return m_element; } >+ >+ bool operator<(const Insertion& other) const >+ { >+ return m_index < other.m_index; >+ } >+ >+private: >+ size_t m_index; >+ T m_element; >+}; >+ >+template<typename TargetVectorType, typename InsertionVectorType> >+void executeInsertions(TargetVectorType& target, InsertionVectorType& insertions) >+{ >+ if (!insertions.size()) >+ return; >+ target.grow(target.size() + insertions.size()); >+ size_t lastIndex = target.size(); >+ for (size_t indexInInsertions = insertions.size(); indexInInsertions--;) { >+ size_t firstIndex = insertions[indexInInsertions].index() + indexInInsertions; >+ size_t indexOffset = indexInInsertions + 1; >+ for (size_t i = lastIndex; --i > firstIndex;) >+ target[i] = target[i - indexOffset]; >+ target[firstIndex] = insertions[indexInInsertions].element(); >+ lastIndex = firstIndex; >+ } >+ insertions.resize(0); >+} >+ >+} // namespace WTF >+ >+using WTF::Insertion; >+using WTF::executeInsertions; >+ >+#endif // Insertion_h >Index: Source/WTF/wtf/ListDump.h >=================================================================== >--- Source/WTF/wtf/ListDump.h (revision 0) >+++ Source/WTF/wtf/ListDump.h (working copy) >@@ -0,0 +1,136 @@ >+/* >+ * 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 ListDump_h >+#define ListDump_h >+ >+#include "CommaPrinter.h" >+#include "PrintStream.h" >+#include "StringPrintStream.h" >+ >+namespace WTF { >+ >+template<typename T> >+class ListDump { >+public: >+ ListDump(const T& list, const char* comma) >+ : m_list(list) >+ , m_comma(comma) >+ { >+ } >+ >+ void dump(PrintStream& out) const >+ { >+ for (typename T::const_iterator iter = m_list.begin(); iter != m_list.end(); ++iter) >+ out.print(m_comma, *iter); >+ } >+ >+private: >+ const T& m_list; >+ CommaPrinter m_comma; >+}; >+ >+template<typename T> >+class MapDump { >+public: >+ MapDump(const T& map, const char* arrow, const char* comma) >+ : m_map(map) >+ , m_arrow(arrow) >+ , m_comma(comma) >+ { >+ } >+ >+ void dump(PrintStream& out) const >+ { >+ for (typename T::const_iterator iter = m_map.begin(); iter != m_map.end(); ++iter) >+ out.print(m_comma, iter->key, m_arrow, iter->value); >+ } >+ >+private: >+ const T& m_map; >+ const char* m_arrow; >+ CommaPrinter m_comma; >+}; >+ >+template<typename T> >+ListDump<T> listDump(const T& list, const char* comma = ", ") >+{ >+ return ListDump<T>(list, comma); >+} >+ >+template<typename T, typename Comparator> >+CString sortedListDump(const T& list, const Comparator& comparator, const char* comma = ", ") >+{ >+ Vector<typename T::ValueType> myList; >+ myList.appendRange(list.begin(), list.end()); >+ std::sort(myList.begin(), myList.end(), comparator); >+ StringPrintStream out; >+ CommaPrinter commaPrinter(comma); >+ for (unsigned i = 0; i < myList.size(); ++i) >+ out.print(commaPrinter, myList[i]); >+ return out.toCString(); >+} >+ >+template<typename T> >+inline bool lessThan(const T& a, const T& b) >+{ >+ return a < b; >+} >+ >+template<typename T> >+CString sortedListDump(const T& list, const char* comma = ", ") >+{ >+ return sortedListDump(list, lessThan<T::ValueType>, comma); >+} >+ >+template<typename T> >+MapDump<T> mapDump(const T& map, const char* arrow = "=>", const char* comma = ", ") >+{ >+ return MapDump<T>(map, arrow, comma); >+} >+ >+template<typename T, typename Comparator> >+CString sortedMapDump(const T& map, const Comparator& comparator, const char* arrow = "=>", const char* comma = ", ") >+{ >+ Vector<typename T::KeyType> keys; >+ for (typename T::const_iterator iter = map.begin(); iter != map.end(); ++iter) >+ keys.append(iter->key); >+ std::sort(keys.begin(), keys.end(), comparator); >+ StringPrintStream out; >+ CommaPrinter commaPrinter(comma); >+ for (unsigned i = 0; i < keys.size(); ++i) >+ out.print(commaPrinter, keys[i], arrow, map.get(keys[i])); >+ return out.toCString(); >+} >+ >+} // namespace WTF >+ >+using WTF::listDump; >+using WTF::sortedListDump; >+using WTF::mapDump; >+using WTF::sortedMapDump; >+ >+#endif // ListDump_h >+ >Index: Source/WTF/wtf/PrintStream.h >=================================================================== >--- Source/WTF/wtf/PrintStream.h (revision 152582) >+++ Source/WTF/wtf/PrintStream.h (working copy) >@@ -207,6 +207,45 @@ public: > print(value12); > print(value13); > } >+ >+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14> >+ void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13, const T14& value14) >+ { >+ print(value1); >+ print(value2); >+ print(value3); >+ print(value4); >+ print(value5); >+ print(value6); >+ print(value7); >+ print(value8); >+ print(value9); >+ print(value10); >+ print(value11); >+ print(value12); >+ print(value13); >+ print(value14); >+ } >+ >+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> >+ void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13, const T14& value14, const T15& value15) >+ { >+ print(value1); >+ print(value2); >+ print(value3); >+ print(value4); >+ print(value5); >+ print(value6); >+ print(value7); >+ print(value8); >+ print(value9); >+ print(value10); >+ print(value11); >+ print(value12); >+ print(value13); >+ print(value14); >+ print(value15); >+ } > }; > > WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const char*);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 118338
:
206181
|
206182
|
206183
|
206196
|
206198
|
206199
|
206209
|
206214
|
206254
|
206282
|
206288
|
206290
|
206338
|
206407
|
206408
|
206486
|
206489
|
206503
|
206504
|
206505
|
206561
|
206575
|
206586
|
206589
|
206592