WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
it compiles!
blah.patch (text/plain), 224.82 KB, created by
Filip Pizlo
on 2014-09-22 18:01:57 PDT
(
hide
)
Description:
it compiles!
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2014-09-22 18:01:57 PDT
Size:
224.82 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 173846) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,238 @@ >+2014-09-22 Filip Pizlo <fpizlo@apple.com> >+ >+ FTL should sink object allocations >+ https://bugs.webkit.org/show_bug.cgi?id=136330 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Work in progress. >+ >+ * CMakeLists.txt: >+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * bytecode/StructureSet.h: >+ (JSC::StructureSet::iterator::iterator): >+ (JSC::StructureSet::iterator::operator*): >+ (JSC::StructureSet::iterator::operator++): >+ (JSC::StructureSet::iterator::operator==): >+ (JSC::StructureSet::iterator::operator!=): >+ (JSC::StructureSet::begin): >+ (JSC::StructureSet::end): >+ * dfg/DFGAbstractInterpreter.h: >+ (JSC::DFG::AbstractInterpreter::phiChildren): >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::AbstractInterpreter): >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * dfg/DFGAvailability.h: >+ (JSC::DFG::Availability::shouldUseNode): >+ (JSC::DFG::Availability::isFlushUseful): >+ (JSC::DFG::Availability::isDead): >+ * dfg/DFGAvailabilityMap.cpp: Added. >+ (JSC::DFG::AvailabilityMap::prune): >+ (JSC::DFG::AvailabilityMap::dump): >+ (JSC::DFG::AvailabilityMap::operator==): >+ (JSC::DFG::AvailabilityMap::merge): >+ * dfg/DFGAvailabilityMap.h: Added. >+ (JSC::DFG::AvailabilityMap::forEachAvailability): >+ * dfg/DFGBasicBlock.cpp: >+ (JSC::DFG::BasicBlock::SSAData::SSAData): >+ * dfg/DFGBasicBlock.h: >+ (JSC::DFG::BasicBlock::begin): >+ (JSC::DFG::BasicBlock::end): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::SuccessorsIterable): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::iterator::iterator): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::iterator::operator*): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::iterator::operator++): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::iterator::operator==): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::iterator::operator!=): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::begin): >+ (JSC::DFG::BasicBlock::SuccessorsIterable::end): >+ (JSC::DFG::BasicBlock::successors): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGConstantFoldingPhase.cpp: >+ (JSC::DFG::ConstantFoldingPhase::foldConstants): >+ * dfg/DFGDoesGC.cpp: >+ (JSC::DFG::doesGC): >+ * dfg/DFGFixupPhase.cpp: >+ (JSC::DFG::FixupPhase::fixupNode): >+ * dfg/DFGGraph.cpp: >+ (JSC::DFG::Graph::mergeRelevantToOSR): >+ * dfg/DFGGraph.h: >+ (JSC::DFG::Graph::NaturalBlockIterable::NaturalBlockIterable): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::iterator): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::operator*): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::operator++): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::operator==): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::operator!=): >+ (JSC::DFG::Graph::NaturalBlockIterable::iterator::findNext): >+ (JSC::DFG::Graph::NaturalBlockIterable::begin): >+ (JSC::DFG::Graph::NaturalBlockIterable::end): >+ (JSC::DFG::Graph::blocksInNaturalOrder): >+ (JSC::DFG::Graph::doToChildrenWithNode): >+ (JSC::DFG::Graph::doToChildEdges): >+ (JSC::DFG::Graph::doToChildren): >+ * dfg/DFGHeapLocation.cpp: >+ (WTF::printInternal): >+ * dfg/DFGHeapLocation.h: >+ * dfg/DFGInsertOSRHintsForUpdate.cpp: Added. >+ (JSC::DFG::insertOSRHintsForUpdate): >+ * dfg/DFGInsertOSRHintsForUpdate.h: Added. >+ * dfg/DFGInsertionSet.h: >+ (JSC::DFG::InsertionSet::graph): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::convertToPutByOffsetHint): >+ (JSC::DFG::Node::convertToPutStructureHint): >+ (JSC::DFG::Node::convertToPhantomNewObject): >+ (JSC::DFG::Node::isCellConstant): >+ (JSC::DFG::Node::hasIdentifier): >+ (JSC::DFG::Node::hasTransition): >+ (JSC::DFG::Node::hasStorageAccessData): >+ (JSC::DFG::Node::hasObjectMaterializationData): >+ (JSC::DFG::Node::objectMaterializationData): >+ (JSC::DFG::Node::isPhantomObjectAllocation): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: >+ (JSC::DFG::OSRAvailabilityAnalysisPhase::run): >+ (JSC::DFG::LocalOSRAvailabilityCalculator::endBlock): >+ (JSC::DFG::LocalOSRAvailabilityCalculator::executeNode): >+ * dfg/DFGOSRAvailabilityAnalysisPhase.h: >+ * dfg/DFGObjectAllocationSinkingPhase.cpp: Added. >+ (JSC::DFG::ObjectAllocationSinkingPhase::ObjectAllocationSinkingPhase): >+ (JSC::DFG::ObjectAllocationSinkingPhase::run): >+ (JSC::DFG::ObjectAllocationSinkingPhase::performSinking): >+ (JSC::DFG::ObjectAllocationSinkingPhase::pruneSinkingCandidates): >+ (JSC::DFG::ObjectAllocationSinkingPhase::determineMaterializationPoints): >+ (JSC::DFG::ObjectAllocationSinkingPhase::placeMaterializationPoints): >+ (JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations): >+ (JSC::DFG::ObjectAllocationSinkingPhase::promoteSunkenFields): >+ (JSC::DFG::ObjectAllocationSinkingPhase::resolve): >+ (JSC::DFG::ObjectAllocationSinkingPhase::doNothing): >+ (JSC::DFG::ObjectAllocationSinkingPhase::handleNode): >+ (JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize): >+ (JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize): >+ (JSC::DFG::performObjectAllocationSinking): >+ * dfg/DFGObjectAllocationSinkingPhase.h: Added. >+ * dfg/DFGObjectMaterializationData.cpp: Added. >+ (JSC::DFG::PhantomPropertyValue::dump): >+ (JSC::DFG::ObjectMaterializationData::dump): >+ (JSC::DFG::ObjectMaterializationData::oneWaySimilarityScore): >+ (JSC::DFG::ObjectMaterializationData::similarityScore): >+ * dfg/DFGObjectMaterializationData.h: Added. >+ (JSC::DFG::PhantomPropertyValue::PhantomPropertyValue): >+ (JSC::DFG::PhantomPropertyValue::operator==): >+ * dfg/DFGPhantomCanonicalizationPhase.cpp: >+ (JSC::DFG::PhantomCanonicalizationPhase::run): >+ * dfg/DFGPhantomRemovalPhase.cpp: >+ (JSC::DFG::PhantomRemovalPhase::run): >+ * dfg/DFGPhiChildren.cpp: Added. >+ (JSC::DFG::PhiChildren::PhiChildren): >+ (JSC::DFG::PhiChildren::~PhiChildren): >+ (JSC::DFG::PhiChildren::childrenOf): >+ * dfg/DFGPhiChildren.h: Added. >+ (JSC::DFG::PhiChildren::forAllIncomingValues): >+ (JSC::DFG::PhiChildren::forAllTransitiveIncomingValues): >+ * dfg/DFGPlan.cpp: >+ (JSC::DFG::Plan::compileInThreadImpl): >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ (JSC::DFG::PredictionPropagationPhase::propagate): >+ * dfg/DFGPromotedHeapLocation.cpp: Added. >+ (JSC::DFG::BaselessPromotedHeapLocation::dump): >+ (JSC::DFG::PromotedHeapLocation::createHint): >+ (JSC::DFG::PromotedHeapLocation::dump): >+ (WTF::printInternal): >+ * dfg/DFGPromotedHeapLocation.h: Added. >+ (JSC::DFG::BaselessPromotedHeapLocation::BaselessPromotedHeapLocation): >+ (JSC::DFG::BaselessPromotedHeapLocation::operator!): >+ (JSC::DFG::BaselessPromotedHeapLocation::kind): >+ (JSC::DFG::BaselessPromotedHeapLocation::info): >+ (JSC::DFG::BaselessPromotedHeapLocation::hash): >+ (JSC::DFG::BaselessPromotedHeapLocation::operator==): >+ (JSC::DFG::BaselessPromotedHeapLocation::isHashTableDeletedValue): >+ (JSC::DFG::PromotedHeapLocation::PromotedHeapLocation): >+ (JSC::DFG::PromotedHeapLocation::PromotedHeapLocaftion): >+ (JSC::DFG::PromotedHeapLocation::operator!): >+ (JSC::DFG::PromotedHeapLocation::kind): >+ (JSC::DFG::PromotedHeapLocation::base): >+ (JSC::DFG::PromotedHeapLocation::info): >+ (JSC::DFG::PromotedHeapLocation::baseless): >+ (JSC::DFG::PromotedHeapLocation::hash): >+ (JSC::DFG::PromotedHeapLocation::operator==): >+ (JSC::DFG::PromotedHeapLocation::isHashTableDeletedValue): >+ (JSC::DFG::promote): >+ (JSC::DFG::PromotedHeapLocationHash::hash): >+ (JSC::DFG::PromotedHeapLocationHash::equal): >+ * dfg/DFGSSACalculator.cpp: >+ (JSC::DFG::SSACalculator::reset): >+ * dfg/DFGSSACalculator.h: >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT32_64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * ftl/FTLCapabilities.cpp: >+ (JSC::FTL::canCompile): >+ * ftl/FTLExitPropertyValue.cpp: Added. >+ (JSC::FTL::ExitPropertyValue::dump): >+ * ftl/FTLExitPropertyValue.h: Added. >+ (JSC::FTL::ExitPropertyValue::ExitPropertyValue): >+ (JSC::FTL::ExitPropertyValue::operator!): >+ (JSC::FTL::ExitPropertyValue::location): >+ (JSC::FTL::ExitPropertyValue::value): >+ * ftl/FTLExitTimeObjectMaterialization.cpp: Added. >+ (JSC::FTL::ExitTimeObjectMaterialization::ExitTimeObjectMaterialization): >+ (JSC::FTL::ExitTimeObjectMaterialization::~ExitTimeObjectMaterialization): >+ (JSC::FTL::ExitTimeObjectMaterialization::add): >+ (JSC::FTL::ExitTimeObjectMaterialization::get): >+ (JSC::FTL::ExitTimeObjectMaterialization::dump): >+ * ftl/FTLExitTimeObjectMaterialization.h: Added. >+ (JSC::FTL::ExitTimeObjectMaterialization::type): >+ (JSC::FTL::ExitTimeObjectMaterialization::properties): >+ * ftl/FTLExitValue.cpp: >+ (JSC::FTL::ExitValue::materializeNewObject): >+ (JSC::FTL::ExitValue::dumpInContext): >+ * ftl/FTLExitValue.h: >+ (JSC::FTL::ExitValue::isObjectMaterialization): >+ (JSC::FTL::ExitValue::objectMaterialization): >+ (JSC::FTL::ExitValue::withVirtualRegister): >+ (JSC::FTL::ExitValue::valueFormat): >+ * ftl/FTLLowerDFGToLLVM.cpp: >+ (JSC::FTL::LowerDFGToLLVM::compileNode): >+ (JSC::FTL::LowerDFGToLLVM::compileCheckStructure): >+ (JSC::FTL::LowerDFGToLLVM::compileNewObject): >+ (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset): >+ (JSC::FTL::LowerDFGToLLVM::compileInvalidationPoint): >+ (JSC::FTL::LowerDFGToLLVM::compileCheckStructureImmediate): >+ (JSC::FTL::LowerDFGToLLVM::compileMaterializeNewObject): >+ (JSC::FTL::LowerDFGToLLVM::checkStructure): >+ (JSC::FTL::LowerDFGToLLVM::allocatePropertyStorage): >+ (JSC::FTL::LowerDFGToLLVM::reallocatePropertyStorage): >+ (JSC::FTL::LowerDFGToLLVM::allocatePropertyStorageWithSizeImpl): >+ (JSC::FTL::LowerDFGToLLVM::allocateCell): >+ (JSC::FTL::LowerDFGToLLVM::storeStructure): >+ (JSC::FTL::LowerDFGToLLVM::allocateObject): >+ (JSC::FTL::LowerDFGToLLVM::appendOSRExit): >+ (JSC::FTL::LowerDFGToLLVM::buildExitArguments): >+ (JSC::FTL::LowerDFGToLLVM::exitValueForAvailability): >+ (JSC::FTL::LowerDFGToLLVM::exitValueForNode): >+ (JSC::FTL::LowerDFGToLLVM::availabilityMap): >+ (JSC::FTL::LowerDFGToLLVM::availability): Deleted. >+ * ftl/FTLOSRExit.h: >+ * ftl/FTLOSRExitCompiler.cpp: >+ (JSC::FTL::compileRecovery): >+ (JSC::FTL::compileStub): >+ * ftl/FTLOperations.cpp: Added. >+ (JSC::FTL::operationNewObjectWithButterfly): >+ (JSC::FTL::operationMaterializeObjectInOSR): >+ * ftl/FTLOperations.h: Added. >+ * runtime/JSObject.h: >+ (JSC::JSFinalObject::JSFinalObject): >+ (JSC::JSFinalObject::create): >+ * runtime/Structure.cpp: >+ (JSC::Structure::canUseForAllocationsOf): >+ * runtime/Structure.h: >+ > 2014-09-22 Diego Pino Garcia <dpino@igalia.com> > > Simple ES6 feature: Number constructor extras >Index: Source/JavaScriptCore/CMakeLists.txt >=================================================================== >--- Source/JavaScriptCore/CMakeLists.txt (revision 173837) >+++ Source/JavaScriptCore/CMakeLists.txt (working copy) >@@ -122,6 +122,7 @@ set(JavaScriptCore_SOURCES > dfg/DFGArrayMode.cpp > dfg/DFGAtTailAbstractState.cpp > dfg/DFGAvailability.cpp >+ dfg/DFGAvailabilityMap.cpp > dfg/DFGBackwardsPropagationPhase.cpp > dfg/DFGBasicBlock.cpp > dfg/DFGBinarySwitch.cpp >@@ -164,6 +165,7 @@ set(JavaScriptCore_SOURCES > dfg/DFGGraphSafepoint.cpp > dfg/DFGHeapLocation.cpp > dfg/DFGInPlaceAbstractState.cpp >+ dfg/DFGInsertOSRHintsForUpdate.cpp > dfg/DFGIntegerCheckCombiningPhase.cpp > dfg/DFGInvalidationPointInjectionPhase.cpp > dfg/DFGJITCode.cpp >@@ -192,13 +194,17 @@ set(JavaScriptCore_SOURCES > dfg/DFGOSRExitCompilerCommon.cpp > dfg/DFGOSRExitJumpPlaceholder.cpp > dfg/DFGOSRExitPreparation.cpp >+ dfg/DFGObjectAllocationSinkingPhase.cpp >+ dfg/DFGObjectMaterializationData.cpp > dfg/DFGOperations.cpp > dfg/DFGPhantomCanonicalizationPhase.cpp > dfg/DFGPhantomRemovalPhase.cpp > dfg/DFGPhase.cpp >+ dfg/DFGPhiChildren.cpp > dfg/DFGPlan.cpp > dfg/DFGPredictionInjectionPhase.cpp > dfg/DFGPredictionPropagationPhase.cpp >+ dfg/DFGPromotedHeapLocation.cpp > dfg/DFGPureValue.cpp > dfg/DFGResurrectionForValidationPhase.cpp > dfg/DFGSSACalculator.cpp >@@ -774,7 +780,9 @@ if (ENABLE_FTL_JIT) > ftl/FTLDataSection.cpp > ftl/FTLExitArgument.cpp > ftl/FTLExitArgumentForOperand.cpp >+ ftl/FTLExitPropertyValue.cpp > ftl/FTLExitThunkGenerator.cpp >+ ftl/FTLExitTimeObjectMaterialization.cpp > ftl/FTLExitValue.cpp > ftl/FTLFail.cpp > ftl/FTLForOSREntryJITCode.cpp >@@ -789,6 +797,7 @@ if (ENABLE_FTL_JIT) > ftl/FTLOSREntry.cpp > ftl/FTLOSRExitCompiler.cpp > ftl/FTLOSRExit.cpp >+ ftl/FTLOperations.cpp > ftl/FTLOutput.cpp > ftl/FTLRecoveryOpcode.cpp > ftl/FTLRegisterAtOffset.cpp >Index: Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (revision 173837) >+++ Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (working copy) >@@ -368,6 +368,7 @@ > <ClCompile Include="..\dfg\DFGArrayMode.cpp" /> > <ClCompile Include="..\dfg\DFGAtTailAbstractState.cpp" /> > <ClCompile Include="..\dfg\DFGAvailability.cpp" /> >+ <ClCompile Include="..\dfg\DFGAvailabilityMap.cpp" /> > <ClCompile Include="..\dfg\DFGBackwardsPropagationPhase.cpp" /> > <ClCompile Include="..\dfg\DFGBasicBlock.cpp" /> > <ClCompile Include="..\dfg\DFGBinarySwitch.cpp" /> >@@ -410,6 +411,7 @@ > <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" /> > <ClCompile Include="..\dfg\DFGHeapLocation.cpp" /> > <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp" /> >+ <ClCompile Include="..\dfg\DFGInsertOSRHintsForUpdate.cpp" /> > <ClCompile Include="..\dfg\DFGIntegerCheckCombiningPhase.cpp" /> > <ClCompile Include="..\dfg\DFGInvalidationPointInjectionPhase.cpp" /> > <ClCompile Include="..\dfg\DFGJITCode.cpp" /> >@@ -439,12 +441,16 @@ > <ClCompile Include="..\dfg\DFGOSRExitCompilerCommon.cpp" /> > <ClCompile Include="..\dfg\DFGOSRExitJumpPlaceholder.cpp" /> > <ClCompile Include="..\dfg\DFGOSRExitPreparation.cpp" /> >+ <ClCompile Include="..\dfg\DFGObjectAllocationSinkingPhase.cpp" /> >+ <ClCompile Include="..\dfg\DFGObjectMaterializationData.cpp" /> > <ClCompile Include="..\dfg\DFGPhantomCanonicalizationPhase.cpp" /> > <ClCompile Include="..\dfg\DFGPhantomRemovalPhase.cpp" /> > <ClCompile Include="..\dfg\DFGPhase.cpp" /> >+ <ClCompile Include="..\dfg\DFGPhiChildren.cpp" /> > <ClCompile Include="..\dfg\DFGPlan.cpp" /> > <ClCompile Include="..\dfg\DFGPredictionInjectionPhase.cpp" /> > <ClCompile Include="..\dfg\DFGPredictionPropagationPhase.cpp" /> >+ <ClCompile Include="..\dfg\DFGPromotedHeapLocation.cpp" /> > <ClCompile Include="..\dfg\DFGPureValue.cpp" /> > <ClCompile Include="..\dfg\DFGResurrectionForValidationPhase.cpp" /> > <ClCompile Include="..\dfg\DFGSafepoint.cpp" /> >@@ -493,7 +499,9 @@ > <ClCompile Include="..\ftl\FTLDWARFRegister.cpp" /> > <ClCompile Include="..\ftl\FTLExitArgument.cpp" /> > <ClCompile Include="..\ftl\FTLExitArgumentForOperand.cpp" /> >+ <ClCompile Include="..\ftl\FTLExitPropertyValue.cpp" /> > <ClCompile Include="..\ftl\FTLExitThunkGenerator.cpp" /> >+ <ClCompile Include="..\ftl\FTLExitTimeObjectMaterialization.cpp" /> > <ClCompile Include="..\ftl\FTLExitValue.cpp" /> > <ClCompile Include="..\ftl\FTLFail.cpp" /> > <ClCompile Include="..\ftl\FTLForOSREntryJITCode.cpp" /> >@@ -508,6 +516,7 @@ > <ClCompile Include="..\ftl\FTLOSREntry.cpp" /> > <ClCompile Include="..\ftl\FTLOSRExit.cpp" /> > <ClCompile Include="..\ftl\FTLOSRExitCompiler.cpp" /> >+ <ClCompile Include="..\ftl\FTLOperations.cpp" /> > <ClCompile Include="..\ftl\FTLOutput.cpp" /> > <ClCompile Include="..\ftl\FTLRecoveryOpcode.cpp" /> > <ClCompile Include="..\ftl\FTLRegisterAtOffset.cpp" /> >@@ -993,6 +1002,7 @@ > <ClInclude Include="..\dfg\DFGArrayMode.h" /> > <ClInclude Include="..\dfg\DFGAtTailAbstractState.h" /> > <ClInclude Include="..\dfg\DFGAvailability.h" /> >+ <ClInclude Include="..\dfg\DFGAvailabilityMap.h" /> > <ClInclude Include="..\dfg\DFGBackwardsPropagationPhase.h" /> > <ClInclude Include="..\dfg\DFGBasicBlock.h" /> > <ClInclude Include="..\dfg\DFGBasicBlockInlines.h" /> >@@ -1049,6 +1059,7 @@ > <ClInclude Include="..\dfg\DFGGraphSafepoint.h" /> > <ClInclude Include="..\dfg\DFGHeapLocation.h" /> > <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h" /> >+ <ClInclude Include="..\dfg\DFGInsertOSRHintsForUpdate.h" /> > <ClInclude Include="..\dfg\DFGInsertionSet.h" /> > <ClInclude Include="..\dfg\DFGIntegerCheckCombiningPhase.h" /> > <ClInclude Include="..\dfg\DFGInvalidationPointInjectionPhase.h" /> >@@ -1073,6 +1084,8 @@ > <ClInclude Include="..\dfg\DFGNodeFlags.h" /> > <ClInclude Include="..\dfg\DFGNodeOrigin.h" /> > <ClInclude Include="..\dfg\DFGNodeType.h" /> >+ <ClInclude Include="..\dfg\DFGObjectAllocationSinkingPhase.h" /> >+ <ClInclude Include="..\dfg\DFGObjectMaterializationData.h" /> > <ClInclude Include="..\dfg\DFGOperations.h" /> > <ClInclude Include="..\dfg\DFGOSRAvailabilityAnalysisPhase.h" /> > <ClInclude Include="..\dfg\DFGOSREntry.h" /> >@@ -1087,9 +1100,12 @@ > <ClInclude Include="..\dfg\DFGPhantomCanonicalizationPhase.h" /> > <ClInclude Include="..\dfg\DFGPhantomRemovalPhase.h" /> > <ClInclude Include="..\dfg\DFGPhase.h" /> >+ <ClInclude Include="..\dfg\DFGPhiChildren.h" /> > <ClInclude Include="..\dfg\DFGPlan.h" /> > <ClInclude Include="..\dfg\DFGPredictionInjectionPhase.h" /> > <ClInclude Include="..\dfg\DFGPredictionPropagationPhase.h" /> >+ <ClInclude Include="..\dfg\DFGPromoteHeapAccess.h" /> >+ <ClInclude Include="..\dfg\DFGPromotedHeapLocation.h" /> > <ClInclude Include="..\dfg\DFGPureValue.h" /> > <ClInclude Include="..\dfg\DFGRegisterBank.h" /> > <ClInclude Include="..\dfg\DFGRegisterSet.h" /> >@@ -1150,7 +1166,9 @@ > <ClInclude Include="..\ftl\FTLExitArgument.h" /> > <ClInclude Include="..\ftl\FTLExitArgumentForOperand.h" /> > <ClInclude Include="..\ftl\FTLExitArgumentList.h" /> >+ <ClInclude Include="..\ftl\FTLExitPropertyValue.h" /> > <ClInclude Include="..\ftl\FTLExitThunkGenerator.h" /> >+ <ClInclude Include="..\ftl\FTLExitTimeObjectMaterialization.h" /> > <ClInclude Include="..\ftl\FTLExitValue.h" /> > <ClInclude Include="..\ftl\FTLFail.h" /> > <ClInclude Include="..\ftl\FTLFormattedValue.h" /> >@@ -1170,6 +1188,7 @@ > <ClInclude Include="..\ftl\FTLOSRExit.h" /> > <ClInclude Include="..\ftl\FTLOSRExitCompilationInfo.h" /> > <ClInclude Include="..\ftl\FTLOSRExitCompiler.h" /> >+ <ClInclude Include="..\ftl\FTLOperations.h" /> > <ClInclude Include="..\ftl\FTLOutput.h" /> > <ClInclude Include="..\ftl\FTLRecoveryOpcode.h" /> > <ClInclude Include="..\ftl\FTLRegisterAtOffset.h" /> >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 173837) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -209,6 +209,24 @@ > 0F2B670917B6B5AB00A7AE3F /* TypedArrays.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66DB17B6B5AB00A7AE3F /* TypedArrays.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F2B670A17B6B5AB00A7AE3F /* TypedArrayType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66DC17B6B5AB00A7AE3F /* TypedArrayType.cpp */; }; > 0F2B670B17B6B5AB00A7AE3F /* TypedArrayType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66DD17B6B5AB00A7AE3F /* TypedArrayType.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CE219D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CD619D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp */; }; >+ 0F2B9CE319D0BA7D00B1D1B5 /* DFGAvailabilityMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CD719D0BA7D00B1D1B5 /* DFGAvailabilityMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CE419D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CD819D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp */; }; >+ 0F2B9CE519D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CD919D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CE619D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CDA19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.cpp */; }; >+ 0F2B9CE719D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CDB19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CE819D0BA7D00B1D1B5 /* DFGObjectMaterializationData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CDC19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.cpp */; }; >+ 0F2B9CE919D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CDD19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CEA19D0BA7D00B1D1B5 /* DFGPhiChildren.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CDE19D0BA7D00B1D1B5 /* DFGPhiChildren.cpp */; }; >+ 0F2B9CEB19D0BA7D00B1D1B5 /* DFGPhiChildren.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CDF19D0BA7D00B1D1B5 /* DFGPhiChildren.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CEC19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */; }; >+ 0F2B9CED19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CF419D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CEE19D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp */; }; >+ 0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CEF19D0BAC100B1D1B5 /* FTLExitPropertyValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CF619D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CF019D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.cpp */; }; >+ 0F2B9CF719D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CF119D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F2B9CF819D0BAC100B1D1B5 /* FTLOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B9CF219D0BAC100B1D1B5 /* FTLOperations.cpp */; }; >+ 0F2B9CF919D0BAC100B1D1B5 /* FTLOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B9CF319D0BAC100B1D1B5 /* FTLOperations.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */; }; > 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -443,6 +461,7 @@ > 0FA7A8EB18B413C80052371D /* Reg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA7A8E918B413C80052371D /* Reg.cpp */; }; > 0FA7A8EC18B413C80052371D /* Reg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA7A8EA18B413C80052371D /* Reg.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FA7A8EE18CE4FD80052371D /* ScratchRegisterAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA7A8ED18CE4FD80052371D /* ScratchRegisterAllocator.cpp */; }; >+ 0FAA3E0919D0C2CB00FAC9E2 /* DFGPromoteHeapAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAA3E0819D0C2CB00FAC9E2 /* DFGPromoteHeapAccess.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FAF7EFD165BA91B000C8455 /* JITDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FAF7EFA165BA919000C8455 /* JITDisassembler.cpp */; }; > 0FAF7EFE165BA91F000C8455 /* JITDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAF7EFB165BA919000C8455 /* JITDisassembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FB105851675480F00F8AB6E /* ExitKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB105821675480C00F8AB6E /* ExitKind.cpp */; }; >@@ -1831,6 +1850,24 @@ > 0F2B66DB17B6B5AB00A7AE3F /* TypedArrays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrays.h; sourceTree = "<group>"; }; > 0F2B66DC17B6B5AB00A7AE3F /* TypedArrayType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypedArrayType.cpp; sourceTree = "<group>"; }; > 0F2B66DD17B6B5AB00A7AE3F /* TypedArrayType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrayType.h; sourceTree = "<group>"; }; >+ 0F2B9CD619D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAvailabilityMap.cpp; path = dfg/DFGAvailabilityMap.cpp; sourceTree = "<group>"; }; >+ 0F2B9CD719D0BA7D00B1D1B5 /* DFGAvailabilityMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAvailabilityMap.h; path = dfg/DFGAvailabilityMap.h; sourceTree = "<group>"; }; >+ 0F2B9CD819D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInsertOSRHintsForUpdate.cpp; path = dfg/DFGInsertOSRHintsForUpdate.cpp; sourceTree = "<group>"; }; >+ 0F2B9CD919D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInsertOSRHintsForUpdate.h; path = dfg/DFGInsertOSRHintsForUpdate.h; sourceTree = "<group>"; }; >+ 0F2B9CDA19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGObjectAllocationSinkingPhase.cpp; path = dfg/DFGObjectAllocationSinkingPhase.cpp; sourceTree = "<group>"; }; >+ 0F2B9CDB19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGObjectAllocationSinkingPhase.h; path = dfg/DFGObjectAllocationSinkingPhase.h; sourceTree = "<group>"; }; >+ 0F2B9CDC19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGObjectMaterializationData.cpp; path = dfg/DFGObjectMaterializationData.cpp; sourceTree = "<group>"; }; >+ 0F2B9CDD19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGObjectMaterializationData.h; path = dfg/DFGObjectMaterializationData.h; sourceTree = "<group>"; }; >+ 0F2B9CDE19D0BA7D00B1D1B5 /* DFGPhiChildren.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhiChildren.cpp; path = dfg/DFGPhiChildren.cpp; sourceTree = "<group>"; }; >+ 0F2B9CDF19D0BA7D00B1D1B5 /* DFGPhiChildren.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhiChildren.h; path = dfg/DFGPhiChildren.h; sourceTree = "<group>"; }; >+ 0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPromotedHeapLocation.cpp; path = dfg/DFGPromotedHeapLocation.cpp; sourceTree = "<group>"; }; >+ 0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPromotedHeapLocation.h; path = dfg/DFGPromotedHeapLocation.h; sourceTree = "<group>"; }; >+ 0F2B9CEE19D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLExitPropertyValue.cpp; path = ftl/FTLExitPropertyValue.cpp; sourceTree = "<group>"; }; >+ 0F2B9CEF19D0BAC100B1D1B5 /* FTLExitPropertyValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLExitPropertyValue.h; path = ftl/FTLExitPropertyValue.h; sourceTree = "<group>"; }; >+ 0F2B9CF019D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLExitTimeObjectMaterialization.cpp; path = ftl/FTLExitTimeObjectMaterialization.cpp; sourceTree = "<group>"; }; >+ 0F2B9CF119D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLExitTimeObjectMaterialization.h; path = ftl/FTLExitTimeObjectMaterialization.h; sourceTree = "<group>"; }; >+ 0F2B9CF219D0BAC100B1D1B5 /* FTLOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLOperations.cpp; path = ftl/FTLOperations.cpp; sourceTree = "<group>"; }; >+ 0F2B9CF319D0BAC100B1D1B5 /* FTLOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLOperations.h; path = ftl/FTLOperations.h; sourceTree = "<group>"; }; > 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFixupPhase.cpp; path = dfg/DFGFixupPhase.cpp; sourceTree = "<group>"; }; > 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFixupPhase.h; path = dfg/DFGFixupPhase.h; sourceTree = "<group>"; }; > 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInsertionSet.h; path = dfg/DFGInsertionSet.h; sourceTree = "<group>"; }; >@@ -2062,6 +2099,7 @@ > 0FA7A8E918B413C80052371D /* Reg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Reg.cpp; sourceTree = "<group>"; }; > 0FA7A8EA18B413C80052371D /* Reg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reg.h; sourceTree = "<group>"; }; > 0FA7A8ED18CE4FD80052371D /* ScratchRegisterAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScratchRegisterAllocator.cpp; sourceTree = "<group>"; }; >+ 0FAA3E0819D0C2CB00FAC9E2 /* DFGPromoteHeapAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPromoteHeapAccess.h; path = dfg/DFGPromoteHeapAccess.h; sourceTree = "<group>"; }; > 0FAF7EFA165BA919000C8455 /* JITDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITDisassembler.cpp; sourceTree = "<group>"; }; > 0FAF7EFB165BA919000C8455 /* JITDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDisassembler.h; sourceTree = "<group>"; }; > 0FB105821675480C00F8AB6E /* ExitKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExitKind.cpp; sourceTree = "<group>"; }; >@@ -3471,8 +3509,12 @@ > 0F235BBF17178E1C00690C7F /* FTLExitArgumentForOperand.cpp */, > 0F235BC017178E1C00690C7F /* FTLExitArgumentForOperand.h */, > 0F235BC117178E1C00690C7F /* FTLExitArgumentList.h */, >+ 0F2B9CEE19D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp */, >+ 0F2B9CEF19D0BAC100B1D1B5 /* FTLExitPropertyValue.h */, > 0F235BC217178E1C00690C7F /* FTLExitThunkGenerator.cpp */, > 0F235BC317178E1C00690C7F /* FTLExitThunkGenerator.h */, >+ 0F2B9CF019D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.cpp */, >+ 0F2B9CF119D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.h */, > 0F235BC417178E1C00690C7F /* FTLExitValue.cpp */, > 0F235BC517178E1C00690C7F /* FTLExitValue.h */, > A7F2996917A0BB670010417A /* FTLFail.cpp */, >@@ -3499,6 +3541,8 @@ > 0FEA0A04170513DB00BB722C /* FTLLowerDFGToLLVM.cpp */, > 0FEA0A05170513DB00BB722C /* FTLLowerDFGToLLVM.h */, > A7D89D0117A0B90400773AD8 /* FTLLoweredNodeValue.h */, >+ 0F2B9CF219D0BAC100B1D1B5 /* FTLOperations.cpp */, >+ 0F2B9CF319D0BAC100B1D1B5 /* FTLOperations.h */, > 0FD8A31717D51F2200CA2C40 /* FTLOSREntry.cpp */, > 0FD8A31817D51F2200CA2C40 /* FTLOSREntry.h */, > 0F235BC617178E1C00690C7F /* FTLOSRExit.cpp */, >@@ -4528,6 +4572,8 @@ > A7D9A29017A0BC7400EE2618 /* DFGAtTailAbstractState.h */, > 0F666EC21835672B00D017F1 /* DFGAvailability.cpp */, > 0F666EC31835672B00D017F1 /* DFGAvailability.h */, >+ 0F2B9CD619D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp */, >+ 0F2B9CD719D0BA7D00B1D1B5 /* DFGAvailabilityMap.h */, > 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */, > 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */, > A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */, >@@ -4626,6 +4672,8 @@ > A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */, > A704D90117A0BAA8006BA554 /* DFGInPlaceAbstractState.h */, > 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */, >+ 0F2B9CD819D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp */, >+ 0F2B9CD919D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.h */, > 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */, > 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */, > 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */, >@@ -4666,6 +4714,10 @@ > 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */, > 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */, > 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */, >+ 0F2B9CDA19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.cpp */, >+ 0F2B9CDB19D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h */, >+ 0F2B9CDC19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.cpp */, >+ 0F2B9CDD19D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h */, > 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */, > 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */, > A7D89CEE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.cpp */, >@@ -4695,12 +4747,17 @@ > 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */, > 0FFFC94F14EF909500C72532 /* DFGPhase.cpp */, > 0FFFC95014EF909500C72532 /* DFGPhase.h */, >+ 0F2B9CDE19D0BA7D00B1D1B5 /* DFGPhiChildren.cpp */, >+ 0F2B9CDF19D0BA7D00B1D1B5 /* DFGPhiChildren.h */, > A78A9772179738B8009DF744 /* DFGPlan.cpp */, > A78A9773179738B8009DF744 /* DFGPlan.h */, > 0FBE0F6D16C1DB010082C5E8 /* DFGPredictionInjectionPhase.cpp */, > 0FBE0F6E16C1DB010082C5E8 /* DFGPredictionInjectionPhase.h */, > 0FFFC95114EF909500C72532 /* DFGPredictionPropagationPhase.cpp */, > 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */, >+ 0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */, >+ 0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */, >+ 0FAA3E0819D0C2CB00FAC9E2 /* DFGPromoteHeapAccess.h */, > 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */, > 0FB1765F196B8F9E0091052A /* DFGPureValue.h */, > 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */, >@@ -5281,6 +5338,7 @@ > A5D2E665195E174000A518E7 /* JSContextRefInternal.h in Headers */, > A7D801A51880D66E0026C39B /* BuiltinExecutables.h in Headers */, > A75EE9B218AAB7E200AAD043 /* BuiltinNames.h in Headers */, >+ 0F2B9CF719D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.h in Headers */, > 0FB7F39715ED8E4600F167B2 /* Butterfly.h in Headers */, > 0FB7F39815ED8E4600F167B2 /* ButterflyInlines.h in Headers */, > C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */, >@@ -5339,6 +5397,7 @@ > 2A68295B1875F80500B6C3E2 /* CopyWriteBarrier.h in Headers */, > 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, > 0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */, >+ 0F2B9CE519D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.h in Headers */, > 0F2B66DF17B6B5AB00A7AE3F /* DataView.h in Headers */, > BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */, > 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */, >@@ -5426,10 +5485,12 @@ > A78A9779179738B8009DF744 /* DFGJITFinalizer.h in Headers */, > 0FC97F4018202119002C9B26 /* DFGJumpReplacement.h in Headers */, > A73A535B1799CD5D00170C19 /* DFGLazyJSValue.h in Headers */, >+ 0F2B9CE919D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h in Headers */, > A7D9A29817A0BC7400EE2618 /* DFGLICMPhase.h in Headers */, > A7D89CFC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h in Headers */, > 0FF0F19B16B729FA005DF95B /* DFGLongLivedState.h in Headers */, > A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */, >+ 0F2B9CED19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h in Headers */, > A704D90717A0BAA8006BA554 /* DFGMergeMode.h in Headers */, > 0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */, > 0F2BDC451522801B00CD8910 /* DFGMinifiedGraph.h in Headers */, >@@ -5486,6 +5547,7 @@ > 0F2BDC471522802500CD8910 /* DFGValueRecoveryOverride.h in Headers */, > 0F2BDC481522802900CD8910 /* DFGValueSource.h in Headers */, > 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */, >+ 0FAA3E0919D0C2CB00FAC9E2 /* DFGPromoteHeapAccess.h in Headers */, > 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */, > 0F2BDC491522809600CD8910 /* DFGVariableEvent.h in Headers */, > 0F2BDC4B1522809D00CD8910 /* DFGVariableEventStream.h in Headers */, >@@ -5647,6 +5709,7 @@ > 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */, > 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */, > BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */, >+ 0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */, > A503FA1A188E0FB000110F14 /* JavaScriptCallFrame.h in Headers */, > BC18C4140E16F5CD00B34460 /* JavaScriptCore.h in Headers */, > BC18C4150E16F5CD00B34460 /* JavaScriptCorePrefix.h in Headers */, >@@ -5690,6 +5753,7 @@ > 657CF45919BF6662004ACBF2 /* JSCallee.h in Headers */, > BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */, > BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */, >+ 0F2B9CF919D0BAC100B1D1B5 /* FTLOperations.h in Headers */, > BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */, > BC18C41C0E16F5CD00B34460 /* JSCallbackObjectFunctions.h in Headers */, > A7D801A91880D6A80026C39B /* JSCBuiltins.h in Headers */, >@@ -5790,6 +5854,7 @@ > BC18C42D0E16F5CD00B34460 /* JSEnvironmentRecord.h in Headers */, > 86E3C615167BABD7006D760A /* JSVirtualMachine.h in Headers */, > 86E3C61D167BABEE006D760A /* JSVirtualMachineInternal.h in Headers */, >+ 0F2B9CE719D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h in Headers */, > A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */, > A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */, > A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */, >@@ -5904,6 +5969,7 @@ > 0F13912A16771C36009CCB07 /* ProfilerBytecodeSequence.h in Headers */, > 0FF729BA166AD360000F5BA3 /* ProfilerCompilation.h in Headers */, > 0FF729BB166AD360000F5BA3 /* ProfilerCompilationKind.h in Headers */, >+ 0F2B9CE319D0BA7D00B1D1B5 /* DFGAvailabilityMap.h in Headers */, > 0FF729BC166AD360000F5BA3 /* ProfilerCompiledBytecode.h in Headers */, > 0FF729BD166AD360000F5BA3 /* ProfilerDatabase.h in Headers */, > 2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */, >@@ -6011,6 +6077,7 @@ > 0FD2C92416D01EE900C7803F /* StructureInlines.h in Headers */, > C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */, > C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */, >+ 0F2B9CEB19D0BA7D00B1D1B5 /* DFGPhiChildren.h in Headers */, > 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */, > 0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */, > BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */, >@@ -6579,6 +6646,7 @@ > 1429D8DD0ED2205B00B89619 /* CallFrame.cpp in Sources */, > 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */, > 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */, >+ 0F2B9CE419D0BA7D00B1D1B5 /* DFGInsertOSRHintsForUpdate.cpp in Sources */, > 0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */, > 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, > 0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */, >@@ -6623,12 +6691,14 @@ > A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */, > 0F666EC61835672B00D017F1 /* DFGAvailability.cpp in Sources */, > 0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */, >+ 0F2B9CEC19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp in Sources */, > A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */, > A70B083217A0B79B00DAF14B /* DFGBinarySwitch.cpp in Sources */, > 2A88067819107D5500CB0BBB /* DFGFunctionWhitelist.cpp in Sources */, > A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */, > 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */, > 0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */, >+ 0F2B9CE619D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.cpp in Sources */, > 0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */, > 0F3B3A271544C995003ED0FF /* DFGCFGSimplificationPhase.cpp in Sources */, > A77A423F17A0BBFD00A8DB81 /* DFGClobberize.cpp in Sources */, >@@ -6651,6 +6721,8 @@ > 0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */, > 0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */, > 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */, >+ 0F2B9CE219D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp in Sources */, >+ 0F2B9CE819D0BA7D00B1D1B5 /* DFGObjectMaterializationData.cpp in Sources */, > 0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */, > 0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */, > 0F0123321944EA1B00843A0C /* DFGValueStrength.cpp in Sources */, >@@ -6767,6 +6839,7 @@ > 0FC3CCFF19ADA410006AC72A /* DFGBlockWorklist.cpp in Sources */, > 0FEA0A0D170513DB00BB722C /* FTLJITCode.cpp in Sources */, > A78A9780179738D5009DF744 /* FTLJITFinalizer.cpp in Sources */, >+ 0F2B9CF419D0BAC100B1D1B5 /* FTLExitPropertyValue.cpp in Sources */, > 0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */, > 0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */, > 0FCEFADF180738C000472CE4 /* FTLLocation.cpp in Sources */, >@@ -6818,6 +6891,7 @@ > 0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */, > A5CEEE14187F3BAD00E55C99 /* InspectorAgent.cpp in Sources */, > A593CF86184038CA00BFCE27 /* InspectorAgentRegistry.cpp in Sources */, >+ 0F2B9CF619D0BAC100B1D1B5 /* FTLExitTimeObjectMaterialization.cpp in Sources */, > A593CF7C1840360300BFCE27 /* InspectorBackendDispatcher.cpp in Sources */, > 2AF7382C18BBBF92008A5A37 /* StructureIDTable.cpp in Sources */, > A5FD0081189B191A00633231 /* InspectorConsoleAgent.cpp in Sources */, >@@ -6997,6 +7071,7 @@ > 0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */, > 0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */, > 95742F650DD11F5A000917FB /* Profile.cpp in Sources */, >+ 0F2B9CF819D0BAC100B1D1B5 /* FTLOperations.cpp in Sources */, > 95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */, > 95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */, > 0FF729AD166AD35C000F5BA3 /* ProfilerBytecode.cpp in Sources */, >@@ -7088,6 +7163,7 @@ > 0FF42745158EBE91004CB9FF /* udis86_syn-att.c in Sources */, > 0FF42746158EBE91004CB9FF /* udis86_syn-intel.c in Sources */, > 0FF42747158EBE91004CB9FF /* udis86_syn.c in Sources */, >+ 0F2B9CEA19D0BA7D00B1D1B5 /* DFGPhiChildren.cpp in Sources */, > 0FF42732158EBD58004CB9FF /* UDis86Disassembler.cpp in Sources */, > A76F279415F13C9600517D67 /* UnlinkedCodeBlock.cpp in Sources */, > B59F89391891F29F00D5CCDC /* UnlinkedInstructionStream.cpp in Sources */, >Index: Source/JavaScriptCore/bytecode/StructureSet.h >=================================================================== >--- Source/JavaScriptCore/bytecode/StructureSet.h (revision 173837) >+++ Source/JavaScriptCore/bytecode/StructureSet.h (working copy) >@@ -166,6 +166,37 @@ public: > return structureList()->list()[structureList()->m_length - 1]; > } > >+ class iterator { >+ public: >+ iterator() >+ : m_set(nullptr) >+ , m_index(0) >+ { >+ } >+ >+ iterator(const StructureSet* set, size_t index) >+ : m_set(set) >+ , m_index(index) >+ { >+ } >+ >+ Structure* operator*() const { return m_set->at(m_index); } >+ iterator& operator++() >+ { >+ m_index++; >+ return *this; >+ } >+ bool operator==(const iterator& other) const { return m_index == other.m_index; } >+ bool operator!=(const iterator& other) const { return !(*this == other); } >+ >+ private: >+ const StructureSet* m_set; >+ size_t m_index; >+ }; >+ >+ iterator begin() const { return iterator(this, 0); } >+ iterator end() const { return iterator(this, size()); } >+ > bool operator==(const StructureSet& other) const; > > SpeculatedType speculationFromStructures() const; >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (working copy) >@@ -32,6 +32,7 @@ > #include "DFGBranchDirection.h" > #include "DFGGraph.h" > #include "DFGNode.h" >+#include "DFGPhiChildren.h" > > namespace JSC { namespace DFG { > >@@ -146,6 +147,8 @@ public: > FiltrationResult filter(AbstractValue&, SpeculatedType); > FiltrationResult filterByValue(AbstractValue&, FrozenValue); > >+ PhiChildren* phiChildren() { return m_phiChildren.get(); } >+ > private: > void clobberWorld(const CodeOrigin&, unsigned indexInBlock); > void clobberCapturedVars(const CodeOrigin&); >@@ -195,6 +198,7 @@ private: > CodeBlock* m_codeBlock; > Graph& m_graph; > AbstractStateType& m_state; >+ std::unique_ptr<PhiChildren> m_phiChildren; > }; > > } } // namespace JSC::DFG >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -43,6 +43,8 @@ AbstractInterpreter<AbstractStateType>:: > , m_graph(graph) > , m_state(state) > { >+ if (m_graph.m_form == SSA) >+ m_phiChildren = std::make_unique<PhiChildren>(m_graph); > } > > template<typename AbstractStateType> >@@ -1260,6 +1262,29 @@ bool AbstractInterpreter<AbstractStateTy > forNode(node).set(m_graph, node->structure()); > break; > >+ case PhantomNewObject: >+ m_state.setDidClobber(true); // Prevent constant folding. >+ break; >+ >+ case PutByOffsetHint: >+ case PutStructureHint: >+ break; >+ >+ case MaterializeNewObject: { >+ StructureSet set; >+ >+ m_phiChildren->forAllTransitiveIncomingValues( >+ m_graph.varArgChild(node, 0).node(), >+ [&] (Node* incoming) { >+ Structure* structure = incoming->dynamicCastConstant<Structure*>(); >+ DFG_ASSERT(m_graph, node, structure); >+ set.add(structure); >+ }); >+ >+ forNode(node).set(m_graph, set); >+ break; >+ } >+ > case CreateActivation: > forNode(node).set( > m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure()); >@@ -1459,7 +1484,6 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case CheckStructure: { >- // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes). > AbstractValue& value = forNode(node->child1()); > ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. > >@@ -1478,6 +1502,50 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >+ case CheckStructureImmediate: { >+ // FIXME: This currently can only reason about one structure at a time. >+ // https://bugs.webkit.org/show_bug.cgi?id=136988 >+ >+ AbstractValue& value = forNode(node->child1()); >+ StructureSet& set = node->structureSet(); >+ >+ if (value.value()) { >+ if (Structure* structure = jsDynamicCast<Structure*>(value.value())) { >+ if (set.contains(structure)) { >+ m_state.setFoundConstants(true); >+ break; >+ } >+ } >+ m_state.setIsValid(false); >+ break; >+ } >+ >+ if (m_phiChildren) { >+ bool allGood = true; >+ m_phiChildren->forAllTransitiveIncomingValues( >+ node, >+ [&] (Node* incoming) { >+ if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) { >+ if (set.contains(structure)) >+ return; >+ } >+ allGood = false; >+ }); >+ if (allGood) { >+ m_state.setFoundConstants(true); >+ break; >+ } >+ } >+ >+ if (Structure* structure = set.onlyStructure()) { >+ filterByValue(node->child1(), *m_graph.freeze(structure)); >+ break; >+ } >+ >+ // Aw shucks, we can't do anything! >+ break; >+ } >+ > case PutStructure: > if (!forNode(node->child1()).m_structure.isClear()) { > if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) >Index: Source/JavaScriptCore/dfg/DFGAvailability.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAvailability.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGAvailability.h (working copy) >@@ -85,6 +85,7 @@ public: > bool nodeIsUnavailable() const { return m_node == unavailableMarker(); } > > bool hasNode() const { return !nodeIsUndecided() && !nodeIsUnavailable(); } >+ bool shouldUseNode() const { return !isFlushUseful() && hasNode(); } > > Node* node() const > { >@@ -94,6 +95,12 @@ public: > } > > FlushedAt flushedAt() const { return m_flushedAt; } >+ bool isFlushUseful() const >+ { >+ return flushedAt().format() != DeadFlush && flushedAt().format() != ConflictingFlush; >+ } >+ >+ bool isDead() const { return !isFlushUseful() && !hasNode(); } > > bool operator!() const { return nodeIsUnavailable() && flushedAt().format() == ConflictingFlush; } > >@@ -103,6 +110,11 @@ public: > && m_flushedAt == other.m_flushedAt; > } > >+ bool operator!=(const Availability& other) const >+ { >+ return !(*this == other); >+ } >+ > Availability merge(const Availability& other) const > { > return Availability( >Index: Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp (working copy) >@@ -0,0 +1,96 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGAvailabilityMap.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "OperandsInlines.h" >+#include <wtf/ListDump.h> >+ >+namespace JSC { namespace DFG { >+ >+void AvailabilityMap::prune() >+{ >+ if (m_heap.isEmpty()) >+ return; >+ >+ HashSet<Node*> possibleNodes; >+ >+ for (unsigned i = m_locals.size(); i--;) { >+ if (m_locals[i].hasNode()) >+ possibleNodes.add(m_locals[i].node()); >+ } >+ >+ int oldPossibleNodesSize; >+ do { >+ oldPossibleNodesSize = possibleNodes.size(); >+ for (auto pair : m_heap) { >+ if (pair.value.hasNode() && possibleNodes.contains(pair.key.base())) >+ possibleNodes.add(pair.value.node()); >+ } >+ } while (oldPossibleNodesSize != possibleNodes.size()); >+ >+ HashMap<PromotedHeapLocation, Availability> newHeap; >+ for (auto pair : m_heap) { >+ if (possibleNodes.contains(pair.key.base())) >+ newHeap.add(pair.key, pair.value); >+ } >+ m_heap = newHeap; >+} >+ >+void AvailabilityMap::clear() >+{ >+ m_locals.fill(Availability()); >+ m_heap.clear(); >+} >+ >+void AvailabilityMap::dump(PrintStream& out) const >+{ >+ out.print("{locals = ", m_locals, "; heap = ", mapDump(m_heap), "}"); >+} >+ >+bool AvailabilityMap::operator==(const AvailabilityMap& other) const >+{ >+ return m_locals == other.m_locals >+ && m_heap == other.m_heap; >+} >+ >+void AvailabilityMap::merge(const AvailabilityMap& other) >+{ >+ for (unsigned i = other.m_locals.size(); i--;) >+ m_locals[i] = other.m_locals[i].merge(m_locals[i]); >+ >+ for (auto pair : other.m_heap) { >+ auto result = m_heap.add(pair.key, Availability()); >+ result.iterator->value = pair.value.merge(result.iterator->value); >+ } >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGAvailabilityMap.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAvailabilityMap.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGAvailabilityMap.h (working copy) >@@ -0,0 +1,64 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGAvailabilityMap_h >+#define DFGAvailabilityMap_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGAvailability.h" >+#include "DFGPromotedHeapLocation.h" >+ >+namespace JSC { namespace DFG { >+ >+struct AvailabilityMap { >+ void prune(); >+ void clear(); >+ >+ void dump(PrintStream& out) const; >+ >+ bool operator==(const AvailabilityMap& other) const; >+ >+ void merge(const AvailabilityMap& other); >+ >+ template<typename Functor> >+ void forEachAvailability(const Functor& functor) >+ { >+ for (unsigned i = m_locals.size(); i--;) >+ functor(m_locals[i]); >+ for (auto pair : m_heap) >+ functor(pair.value); >+ } >+ >+ Operands<Availability> m_locals; >+ HashMap<PromotedHeapLocation, Availability> m_heap; >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGAvailabilityMap_h >+ >Index: Source/JavaScriptCore/dfg/DFGBasicBlock.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBasicBlock.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGBasicBlock.cpp (working copy) >@@ -118,9 +118,9 @@ void BasicBlock::dump(PrintStream& out) > } > > BasicBlock::SSAData::SSAData(BasicBlock* block) >- : availabilityAtHead(OperandsLike, block->variablesAtHead) >- , availabilityAtTail(OperandsLike, block->variablesAtHead) > { >+ availabilityAtHead.m_locals = Operands<Availability>(OperandsLike, block->variablesAtHead); >+ availabilityAtTail.m_locals = Operands<Availability>(OperandsLike, block->variablesAtHead); > } > > BasicBlock::SSAData::~SSAData() { } >Index: Source/JavaScriptCore/dfg/DFGBasicBlock.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBasicBlock.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGBasicBlock.h (working copy) >@@ -30,6 +30,7 @@ > > #include "DFGAbstractValue.h" > #include "DFGAvailability.h" >+#include "DFGAvailabilityMap.h" > #include "DFGBranchDirection.h" > #include "DFGFlushedAt.h" > #include "DFGNode.h" >@@ -46,6 +47,7 @@ class Graph; > class InsertionSet; > > typedef Vector<BasicBlock*, 2> PredecessorList; >+typedef Vector<Node*, 8> BlockNodeList; > > struct BasicBlock : RefCounted<BasicBlock> { > BasicBlock( >@@ -85,6 +87,9 @@ struct BasicBlock : RefCounted<BasicBloc > bool isInPhis(Node* node) const; > bool isInBlock(Node* myNode) const; > >+ BlockNodeList::iterator begin() { return m_nodes.begin(); } >+ BlockNodeList::iterator end() { return m_nodes.end(); } >+ > unsigned numSuccessors() { return last()->numSuccessors(); } > > BasicBlock*& successor(unsigned index) >@@ -96,6 +101,76 @@ struct BasicBlock : RefCounted<BasicBloc > return last()->successorForCondition(condition); > } > >+ class SuccessorsIterable { >+ public: >+ SuccessorsIterable() >+ : m_block(nullptr) >+ { >+ } >+ >+ SuccessorsIterable(BasicBlock* block) >+ : m_block(block) >+ { >+ } >+ >+ class iterator { >+ public: >+ iterator() >+ : m_block(nullptr) >+ , m_index(UINT_MAX) >+ { >+ } >+ >+ iterator(BasicBlock* block, unsigned index) >+ : m_block(block) >+ , m_index(index) >+ { >+ } >+ >+ BasicBlock* operator*() >+ { >+ return m_block->successor(m_index); >+ } >+ >+ iterator& operator++() >+ { >+ m_index++; >+ return *this; >+ } >+ >+ bool operator==(const iterator& other) const >+ { >+ return m_index == other.m_index; >+ } >+ >+ bool operator!=(const iterator& other) const >+ { >+ return !(*this == other); >+ } >+ private: >+ BasicBlock* m_block; >+ unsigned m_index; >+ }; >+ >+ iterator begin() >+ { >+ return iterator(m_block, 0); >+ } >+ >+ iterator end() >+ { >+ return iterator(m_block, m_block->numSuccessors()); >+ } >+ >+ private: >+ BasicBlock* m_block; >+ }; >+ >+ SuccessorsIterable successors() >+ { >+ return SuccessorsIterable(this); >+ } >+ > void removePredecessor(BasicBlock* block); > void replacePredecessor(BasicBlock* from, BasicBlock* to); > >@@ -169,8 +244,9 @@ struct BasicBlock : RefCounted<BasicBloc > unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices]; > > struct SSAData { >- Operands<Availability> availabilityAtHead; >- Operands<Availability> availabilityAtTail; >+ AvailabilityMap availabilityAtHead; >+ AvailabilityMap availabilityAtTail; >+ > HashSet<Node*> liveAtHead; > HashSet<Node*> liveAtTail; > HashMap<Node*, AbstractValue> valuesAtHead; >@@ -183,7 +259,7 @@ struct BasicBlock : RefCounted<BasicBloc > > private: > friend class InsertionSet; >- Vector<Node*, 8> m_nodes; >+ BlockNodeList m_nodes; > }; > > typedef Vector<BasicBlock*, 5> BlockList; >Index: Source/JavaScriptCore/dfg/DFGClobberize.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGClobberize.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -109,6 +109,7 @@ void clobberize(Graph& graph, Node* node > case HardPhantom: > case Check: > case ExtractOSREntryLocal: >+ case CheckStructureImmediate: > return; > > case BitAnd: >@@ -273,6 +274,8 @@ void clobberize(Graph& graph, Node* node > case ProfileDidCall: > case StoreBarrier: > case StoreBarrierWithNullCheck: >+ case PutByOffsetHint: >+ case PutStructureHint: > write(SideState); > return; > >@@ -787,17 +790,15 @@ void clobberize(Graph& graph, Node* node > case NewObject: > case NewRegexp: > case NewStringObject: >- read(HeapObjectCount); >- write(HeapObjectCount); >- return; >- >+ case PhantomNewObject: >+ case MaterializeNewObject: > case NewFunctionNoCheck: > case NewFunction: > case NewFunctionExpression: > read(HeapObjectCount); > write(HeapObjectCount); > return; >- >+ > case RegExpExec: > case RegExpTest: > read(RegExpState); >Index: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (working copy) >@@ -124,6 +124,42 @@ private: > break; > } > >+ case CheckStructureImmediate: { >+ AbstractValue& value = m_state.forNode(node->child1()); >+ StructureSet& set = node->structureSet(); >+ >+ if (value.value()) { >+ if (Structure* structure = jsDynamicCast<Structure*>(value.value())) { >+ if (set.contains(structure)) { >+ m_interpreter.execute(indexInBlock); >+ node->convertToPhantom(); >+ eliminated = true; >+ break; >+ } >+ } >+ } >+ >+ if (PhiChildren* phiChildren = m_interpreter.phiChildren()) { >+ bool allGood = true; >+ phiChildren->forAllTransitiveIncomingValues( >+ node, >+ [&] (Node* incoming) { >+ if (Structure* structure = incoming->dynamicCastConstant<Structure*>()) { >+ if (set.contains(structure)) >+ return; >+ } >+ allGood = false; >+ }); >+ if (allGood) { >+ m_interpreter.execute(indexInBlock); >+ node->convertToPhantom(); >+ eliminated = true; >+ break; >+ } >+ } >+ break; >+ } >+ > case CheckArray: > case Arrayify: { > if (!node->arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node->child1()))) >Index: Source/JavaScriptCore/dfg/DFGDoesGC.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDoesGC.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGDoesGC.cpp (working copy) >@@ -199,6 +199,10 @@ bool doesGC(Graph& graph, Node* node) > case BooleanToNumber: > case CheckBadCell: > case BottomValue: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: > return false; > > case CreateActivation: >@@ -225,6 +229,7 @@ bool doesGC(Graph& graph, Node* node) > case GetGenericPropertyEnumerator: > case GetEnumeratorPname: > case ToIndexString: >+ case MaterializeNewObject: > return true; > > case MultiPutByOffset: >Index: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (working copy) >@@ -1013,6 +1013,11 @@ private: > case Int52Constant: > case Identity: // This should have been cleaned up. > case BooleanToNumber: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: > // These are just nodes that we don't currently expect to see during fixup. > // If we ever wanted to insert them prior to fixup, then we just have to create > // fixup rules for them. >Index: Source/JavaScriptCore/dfg/DFGGraph.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGGraph.cpp (working copy) >@@ -562,6 +562,27 @@ void Graph::resetReachability() > determineReachability(); > } > >+void Graph::mergeRelevantToOSR() >+{ >+ for (BasicBlock* block : blocksInNaturalOrder()) { >+ for (Node* node : *block) { >+ switch (node->op()) { >+ case MovHint: >+ node->child1()->mergeFlags(NodeRelevantToOSR); >+ break; >+ >+ case PutStructureHint: >+ case PutByOffsetHint: >+ node->child2()->mergeFlags(NodeRelevantToOSR); >+ break; >+ >+ default: >+ break; >+ } >+ } >+ } >+} >+ > namespace { > > class RefCountCalculator { >Index: Source/JavaScriptCore/dfg/DFGGraph.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGGraph.h (working copy) >@@ -55,6 +55,47 @@ class ExecState; > > namespace DFG { > >+#define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do { \ >+ Node* _node = (node); \ >+ if (_node->flags() & NodeHasVarArgs) { \ >+ for (unsigned _childIdx = _node->firstChild(); \ >+ _childIdx < _node->firstChild() + _node->numChildren(); \ >+ _childIdx++) { \ >+ if (!!(graph).m_varArgChildren[_childIdx]) \ >+ thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \ >+ } \ >+ } else { \ >+ if (!_node->child1()) { \ >+ ASSERT( \ >+ !_node->child2() \ >+ && !_node->child3()); \ >+ break; \ >+ } \ >+ thingToDo(_node, _node->child1()); \ >+ \ >+ if (!_node->child2()) { \ >+ ASSERT(!_node->child3()); \ >+ break; \ >+ } \ >+ thingToDo(_node, _node->child2()); \ >+ \ >+ if (!_node->child3()) \ >+ break; \ >+ thingToDo(_node, _node->child3()); \ >+ } \ >+ } while (false) >+ >+#define DFG_ASSERT(graph, node, assertion) do { \ >+ if (!!(assertion)) \ >+ break; \ >+ (graph).handleAssertionFailure( \ >+ (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \ >+ } while (false) >+ >+#define DFG_CRASH(graph, node, reason) \ >+ (graph).handleAssertionFailure( \ >+ (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, (reason)); >+ > struct InlineVariableData { > InlineCallFrame* inlineCallFrame; > unsigned argumentPositionStart; >@@ -565,6 +606,8 @@ public: > void determineReachability(); > void resetReachability(); > >+ void mergeRelevantToOSR(); >+ > void computeRefCounts(); > > unsigned varArgNumChildren(Node* node) >@@ -676,6 +719,110 @@ public: > BlockList blocksInPreOrder(); > BlockList blocksInPostOrder(); > >+ class NaturalBlockIterable { >+ public: >+ NaturalBlockIterable() >+ : m_graph(nullptr) >+ { >+ } >+ >+ NaturalBlockIterable(Graph& graph) >+ : m_graph(&graph) >+ { >+ } >+ >+ class iterator { >+ public: >+ iterator() >+ : m_graph(nullptr) >+ , m_index(0) >+ { >+ } >+ >+ iterator(Graph& graph, BlockIndex index) >+ : m_graph(&graph) >+ , m_index(findNext(index)) >+ { >+ } >+ >+ BasicBlock *operator*() >+ { >+ return m_graph->block(m_index); >+ } >+ >+ iterator& operator++() >+ { >+ m_index = findNext(m_index); >+ return *this; >+ } >+ >+ bool operator==(const iterator& other) const >+ { >+ return m_index == other.m_index; >+ } >+ >+ bool operator!=(const iterator& other) const >+ { >+ return !(*this == other); >+ } >+ >+ private: >+ BlockIndex findNext(BlockIndex index) >+ { >+ while (index < m_graph->numBlocks() && !m_graph->block(index)) >+ index++; >+ return index; >+ } >+ >+ Graph* m_graph; >+ BlockIndex m_index; >+ }; >+ >+ iterator begin() >+ { >+ return iterator(*m_graph, 0); >+ } >+ >+ iterator end() >+ { >+ return iterator(*m_graph, m_graph->numBlocks()); >+ } >+ >+ private: >+ Graph* m_graph; >+ }; >+ >+ NaturalBlockIterable blocksInNaturalOrder() >+ { >+ return NaturalBlockIterable(*this); >+ } >+ >+ template<typename ChildFunctor> >+ void doToChildrenWithNode(Node* node, const ChildFunctor& functor) >+ { >+ DFG_NODE_DO_TO_CHILDREN(*this, node, functor); >+ } >+ >+ template<typename ChildFunctor> >+ void doToChildEdges(Node* node, const ChildFunctor& functor) >+ { >+ doToChildrenWithNode( >+ node, >+ [&functor] (Node*, Edge& edge) { >+ functor(edge); >+ }); >+ } >+ >+ template<typename ChildFunctor> >+ void doToChildren(Node* node, const ChildFunctor& functor) >+ { >+ doToChildrenWithNode( >+ node, >+ [&functor] (Node*, Edge edge) { >+ functor(edge); >+ }); >+ } >+ > Profiler::Compilation* compilation() { return m_plan.compilation.get(); } > > DesiredIdentifiers& identifiers() { return m_plan.identifiers; } >@@ -736,6 +883,7 @@ public: > Bag<SwitchData> m_switchData; > Bag<MultiGetByOffsetData> m_multiGetByOffsetData; > Bag<MultiPutByOffsetData> m_multiPutByOffsetData; >+ Bag<ObjectMaterializationData> m_objectMaterializationData; > Vector<InlineVariableData, 4> m_inlineVariableData; > HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness; > bool m_hasArguments; >@@ -786,47 +934,6 @@ private: > } > }; > >-#define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do { \ >- Node* _node = (node); \ >- if (_node->flags() & NodeHasVarArgs) { \ >- for (unsigned _childIdx = _node->firstChild(); \ >- _childIdx < _node->firstChild() + _node->numChildren(); \ >- _childIdx++) { \ >- if (!!(graph).m_varArgChildren[_childIdx]) \ >- thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \ >- } \ >- } else { \ >- if (!_node->child1()) { \ >- ASSERT( \ >- !_node->child2() \ >- && !_node->child3()); \ >- break; \ >- } \ >- thingToDo(_node, _node->child1()); \ >- \ >- if (!_node->child2()) { \ >- ASSERT(!_node->child3()); \ >- break; \ >- } \ >- thingToDo(_node, _node->child2()); \ >- \ >- if (!_node->child3()) \ >- break; \ >- thingToDo(_node, _node->child3()); \ >- } \ >- } while (false) >- >-#define DFG_ASSERT(graph, node, assertion) do { \ >- if (!!(assertion)) \ >- break; \ >- (graph).handleAssertionFailure( \ >- (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \ >- } while (false) >- >-#define DFG_CRASH(graph, node, reason) \ >- (graph).handleAssertionFailure( \ >- (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, (reason)); >- > } } // namespace JSC::DFG > > #endif >Index: Source/JavaScriptCore/dfg/DFGHeapLocation.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (working copy) >@@ -147,6 +147,10 @@ void printInternal(PrintStream& out, Loc > case AllocationProfileWatchpointLoc: > out.print("AllocationProfileWatchpointLoc"); > return; >+ >+ case StructureLoc: >+ out.print("StructureLoc"); >+ return; > } > > RELEASE_ASSERT_NOT_REACHED(); >Index: Source/JavaScriptCore/dfg/DFGHeapLocation.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGHeapLocation.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGHeapLocation.h (working copy) >@@ -55,6 +55,7 @@ enum LocationKind { > MyArgumentsLengthLoc, > NamedPropertyLoc, > SetterLoc, >+ StructureLoc, > TypeOfLoc, > TypedArrayByteOffsetLoc, > VarInjectionWatchpointLoc, >Index: Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.cpp (working copy) >@@ -0,0 +1,58 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGInsertOSRHintsForUpdate.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+void insertOSRHintsForUpdate( >+ InsertionSet& insertionSet, unsigned nodeIndex, AvailabilityMap& availability, >+ Node* originalNode, Node* newNode) >+{ >+ for (unsigned i = availability.m_locals.size(); i--;) { >+ int operand = availability.m_locals.operandForIndex(i); >+ >+ if (availability.m_locals[i].hasNode() && availability.m_locals[i].node() == originalNode) { >+ insertionSet.insertNode( >+ nodeIndex, SpecNone, MovHint, NodeOrigin(), OpInfo(operand), >+ newNode->defaultEdge()); >+ } >+ } >+ >+ for (auto pair : availability.m_heap) { >+ if (pair.value.hasNode() && pair.value.node() == originalNode) { >+ insertionSet.insert( >+ nodeIndex, pair.key.createHint(insertionSet.graph(), NodeOrigin(), newNode)); >+ } >+ } >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGInsertOSRHintsForUpdate.h (working copy) >@@ -0,0 +1,45 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGInsertOSRHintsForUpdate_h >+#define DFGInsertOSRHintsForUpdate_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGInsertionSet.h" >+#include "DFGAvailabilityMap.h" >+ >+namespace JSC { namespace DFG { >+ >+void insertOSRHintsForUpdate( >+ InsertionSet&, unsigned nodeIndex, AvailabilityMap&, >+ Node* originalNode, Node* newNode); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGInsertOSRHintsForUpdate_h >+ >Index: Source/JavaScriptCore/dfg/DFGInsertionSet.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInsertionSet.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGInsertionSet.h (working copy) >@@ -43,6 +43,8 @@ public: > { > } > >+ Graph& graph() { return m_graph; } >+ > Node* insert(const Insertion& insertion) > { > ASSERT(!m_insertions.size() || m_insertions.last().index() <= insertion.index()); >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -38,6 +38,7 @@ > #include "DFGNodeFlags.h" > #include "DFGNodeOrigin.h" > #include "DFGNodeType.h" >+#include "DFGObjectMaterializationData.h" > #include "DFGTransition.h" > #include "DFGUseKind.h" > #include "DFGVariableAccessData.h" >@@ -500,6 +501,35 @@ struct Node { > m_flags &= ~NodeClobbersWorld; > } > >+ void convertToPutByOffsetHint() >+ { >+ ASSERT(m_op == PutByOffset); >+ m_op = PutByOffsetHint; >+ m_opInfo = storageAccessData().identifierNumber; >+ child1() = child2(); >+ child2() = child3(); >+ child3() = Edge(); >+ } >+ >+ void convertToPutStructureHint(Node* structure) >+ { >+ ASSERT(m_op == PutStructure); >+ ASSERT(structure->structure() == transition()->next); >+ m_op = PutStructureHint; >+ m_opInfo = 0; >+ child2() = Edge(structure, KnownCellUse); >+ } >+ >+ void convertToPhantomNewObject() >+ { >+ ASSERT(m_op == NewObject || m_op == MaterializeNewObject); >+ m_op = PhantomNewObject; >+ m_flags &= ~NodeHasVarArgs; >+ m_opInfo = 0; >+ m_opInfo2 = 0; >+ children = AdjacencyList(); >+ } >+ > void convertToPhantomLocal() > { > ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument)); >@@ -580,7 +610,7 @@ struct Node { > > bool isCellConstant() > { >- return isConstant() && constant()->value().isCell(); >+ return isConstant() && constant()->value() && constant()->value().isCell(); > } > > JSCell* asCell() >@@ -704,6 +734,7 @@ struct Node { > case PutById: > case PutByIdFlush: > case PutByIdDirect: >+ case PutByOffsetHint: > return true; > default: > return false; >@@ -1105,6 +1136,7 @@ struct Node { > { > switch (op()) { > case PutStructure: >+ case PutStructureHint: > case AllocatePropertyStorage: > case ReallocatePropertyStorage: > return true; >@@ -1155,7 +1187,14 @@ struct Node { > > bool hasStorageAccessData() > { >- return op() == GetByOffset || op() == GetGetterSetterByOffset || op() == PutByOffset; >+ switch (op()) { >+ case GetByOffset: >+ case PutByOffset: >+ case GetGetterSetterByOffset: >+ return true; >+ default: >+ return false; >+ } > } > > StorageAccessData& storageAccessData() >@@ -1184,6 +1223,26 @@ struct Node { > return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo); > } > >+ bool hasObjectMaterializationData() >+ { >+ return op() == MaterializeNewObject; >+ } >+ >+ ObjectMaterializationData& objectMaterializationData() >+ { >+ return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo); >+ } >+ >+ bool isPhantomObjectAllocation() >+ { >+ switch (op()) { >+ case PhantomNewObject: >+ return true; >+ default: >+ return false; >+ } >+ } >+ > bool hasFunctionDeclIndex() > { > return op() == NewFunction >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -228,6 +228,13 @@ namespace JSC { namespace DFG { > macro(NewTypedArray, NodeResultJS | NodeClobbersWorld | NodeMustGenerate) \ > macro(NewRegexp, NodeResultJS) \ > \ >+ /* Support for allocation sinking. */\ >+ macro(PhantomNewObject, NodeResultJS) \ >+ macro(PutByOffsetHint, NodeMustGenerate) \ >+ macro(CheckStructureImmediate, NodeMustGenerate) \ >+ macro(PutStructureHint, NodeMustGenerate) \ >+ macro(MaterializeNewObject, NodeResultJS | NodeHasVarArgs) \ >+ \ > /* Nodes for misc operations. */\ > macro(Breakpoint, NodeMustGenerate) \ > macro(ProfileWillCall, NodeMustGenerate) \ >Index: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (working copy) >@@ -32,6 +32,7 @@ > #include "DFGGraph.h" > #include "DFGInsertionSet.h" > #include "DFGPhase.h" >+#include "DFGPromoteHeapAccess.h" > #include "JSCInlines.h" > > namespace JSC { namespace DFG { >@@ -51,23 +52,23 @@ public: > BasicBlock* block = m_graph.block(blockIndex); > if (!block) > continue; >- block->ssa->availabilityAtHead.fill(Availability()); >- block->ssa->availabilityAtTail.fill(Availability()); >+ block->ssa->availabilityAtHead.clear(); >+ block->ssa->availabilityAtTail.clear(); > } > > BasicBlock* root = m_graph.block(0); >- for (unsigned argument = root->ssa->availabilityAtHead.numberOfArguments(); argument--;) { >- root->ssa->availabilityAtHead.argument(argument) = >+ for (unsigned argument = root->ssa->availabilityAtHead.m_locals.numberOfArguments(); argument--;) { >+ root->ssa->availabilityAtHead.m_locals.argument(argument) = > Availability::unavailable().withFlush( > FlushedAt(FlushedJSValue, virtualRegisterForArgument(argument))); > } > > if (m_graph.m_plan.mode == FTLForOSREntryMode) { > for (unsigned local = m_graph.m_profiledBlock->m_numCalleeRegisters; local--;) >- root->ssa->availabilityAtHead.local(local) = Availability::unavailable(); >+ root->ssa->availabilityAtHead.m_locals.local(local) = Availability::unavailable(); > } else { >- for (unsigned local = root->ssa->availabilityAtHead.numberOfLocals(); local--;) >- root->ssa->availabilityAtHead.local(local) = Availability::unavailable(); >+ for (unsigned local = root->ssa->availabilityAtHead.m_locals.numberOfLocals(); local--;) >+ root->ssa->availabilityAtHead.m_locals.local(local) = Availability::unavailable(); > } > > // This could be made more efficient by processing blocks in reverse postorder. >@@ -87,6 +88,8 @@ public: > for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) > calculator.executeNode(block->at(nodeIndex)); > >+ calculator.m_availability.prune(); >+ > if (calculator.m_availability == block->ssa->availabilityAtTail) > continue; > >@@ -95,11 +98,7 @@ public: > > for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) { > BasicBlock* successor = block->successor(successorIndex); >- for (unsigned i = calculator.m_availability.size(); i--;) { >- successor->ssa->availabilityAtHead[i] = >- calculator.m_availability[i].merge( >- successor->ssa->availabilityAtHead[i]); >- } >+ successor->ssa->availabilityAtHead.merge(calculator.m_availability); > } > } > } while (changed); >@@ -127,38 +126,50 @@ void LocalOSRAvailabilityCalculator::beg > m_availability = block->ssa->availabilityAtHead; > } > >+void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block) >+{ >+ m_availability = block->ssa->availabilityAtTail; >+} >+ > void LocalOSRAvailabilityCalculator::executeNode(Node* node) > { > switch (node->op()) { > case SetLocal: { > VariableAccessData* variable = node->variableAccessData(); >- m_availability.operand(variable->local()) = >+ m_availability.m_locals.operand(variable->local()) = > Availability(node->child1().node(), variable->flushedAt()); > break; > } > > case GetArgument: { > VariableAccessData* variable = node->variableAccessData(); >- m_availability.operand(variable->local()) = >+ m_availability.m_locals.operand(variable->local()) = > Availability(node, variable->flushedAt()); > break; > } > > case MovHint: { >- m_availability.operand(node->unlinkedLocal()) = >+ m_availability.m_locals.operand(node->unlinkedLocal()) = > Availability(node->child1().node()); > break; > } > > case ZombieHint: { >- m_availability.operand(node->unlinkedLocal()) = >+ m_availability.m_locals.operand(node->unlinkedLocal()) = > Availability::unavailable(); > break; > } >- >+ > default: > break; > } >+ >+ promoteHeapAccess( >+ node, >+ [&] (PromotedHeapLocation location, Edge value) { >+ m_availability.m_heap.set(location, Availability(value.node())); >+ }, >+ [&] (PromotedHeapLocation) { }); > } > > } } // namespace JSC::DFG >Index: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.h (working copy) >@@ -49,9 +49,10 @@ public: > ~LocalOSRAvailabilityCalculator(); > > void beginBlock(BasicBlock*); >+ void endBlock(BasicBlock*); // Useful if you want to get data for the end of the block. You don't need to call this if you did beginBlock() and then executeNode() for every node. > void executeNode(Node*); > >- Operands<Availability> m_availability; >+ AvailabilityMap m_availability; > }; > > } } // namespace JSC::DFG >Index: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (working copy) >@@ -0,0 +1,731 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGObjectAllocationSinkingPhase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGAbstractHeap.h" >+#include "DFGBlockMapInlines.h" >+#include "DFGClobberize.h" >+#include "DFGGraph.h" >+#include "DFGInsertOSRHintsForUpdate.h" >+#include "DFGInsertionSet.h" >+#include "DFGLivenessAnalysisPhase.h" >+#include "DFGOSRAvailabilityAnalysisPhase.h" >+#include "DFGPhase.h" >+#include "DFGPromoteHeapAccess.h" >+#include "DFGSSACalculator.h" >+#include "JSCInlines.h" >+ >+namespace JSC { namespace DFG { >+ >+class ObjectAllocationSinkingPhase : public Phase { >+public: >+ ObjectAllocationSinkingPhase(Graph& graph) >+ : Phase(graph, "object allocation sinking") >+ , m_ssaCalculator(graph) >+ , m_insertionSet(graph) >+ { >+ } >+ >+ bool run() >+ { >+ ASSERT(m_graph.m_fixpointState == FixpointNotConverged); >+ >+ // Logically we wish to consider every NewObject and sink it. However it's definitely not >+ // profitable to sink a NewObject that will always escape. So, first we do a very simple >+ // forward flow analysis that determines the set of NewObject nodes that have any chance >+ // of benefiting from object allocation sinking. Then we fixpoint the following rules: >+ // >+ // - For each NewObject, we turn the original NewObject into a PhantomNewObject and then >+ // we insert MaterializeNewObject just before each escaping site. Note that Upsilons >+ // constitute escaping sites. Then we use forward flow to eliminate unnecessary cases of >+ // MaterializeNewObject. We use the SSACalculator to insert these materializations. If a >+ // Phi is ever created that has the PhantomNewObject as one of its kids, then we insert >+ // a MaterializeNewObject in front of it; this way we never have a Phi that is confused >+ // about whether or not it has the real object. We then turn each PutByOffset over a >+ // PhantomNewObject into a PutByOffsetHint. >+ // >+ // - We perform the same optimization for MaterializeNewObject. This allows us to cover >+ // cases where we had MaterializeNewObject flowing into a PutByOffsetHint. >+ // >+ // We could also add this rule: >+ // >+ // - If all of the Upsilons of a Phi have a MaterializeNewObject that isn't used by anyone >+ // else, then replace the Phi with the MaterializeNewObject. >+ // >+ // FIXME: Implement this. Note that this totally doable but it requires some gnarly >+ // code, and to be effective the pruner needs to be aware of it. Currently any Upsilon >+ // is considered to be an escape even by the pruner, so it's unlikely that we'll see >+ // many cases of Phi over Materializations. >+ // https://bugs.webkit.org/show_bug.cgi?id=136927 >+ >+ if (!performSinking()) >+ return false; >+ >+ while (performSinking()) { } >+ >+ return true; >+ } >+ >+private: >+ bool performSinking() >+ { >+ m_graph.computeRefCounts(); >+ performLivenessAnalysis(m_graph); >+ performOSRAvailabilityAnalysis(m_graph); >+ >+ // We want to only do sinking for those things that would benefit. We use a rough >+ // heuristic: if it's possible for an allocation to make it to a return without escaping, >+ // then we assume that it's worth sinking. It's a simple forward flow problem. >+ // >+ // It just so happens that this forward flow problem also tells us where we would >+ // materialize those nodes that we choose to sink. >+ pruneSinkingCandidates(); >+ if (m_sinkCandidates.isEmpty()) >+ return false; >+ >+ // At this point we are committed to sinking the sinking candidates. >+ determineMaterializationPoints(); >+ placeMaterializationPoints(); >+ lowerNonReadingOperationsOnPhantomAllocations(); >+ promoteSunkenFields(); >+ >+ return true; >+ } >+ >+ void pruneSinkingCandidates() >+ { >+ m_sinkCandidates.clear(); >+ BlockMap<HashSet<Node*>> sinkCandidatesAtHead(m_graph); >+ BlockMap<HashSet<Node*>> sinkCandidatesAtTail(m_graph); >+ >+ bool changed; >+ do { >+ changed = false; >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ HashSet<Node*> sinkCandidates = sinkCandidatesAtHead[block]; >+ for (Node* node : *block) { >+ handleNode( >+ node, >+ [&] () { >+ sinkCandidates.add(node); >+ }, >+ [&] (Node* escapee) { >+ sinkCandidates.remove(escapee); >+ }); >+ } >+ if (sinkCandidatesAtTail[block] == sinkCandidates) >+ continue; >+ >+ sinkCandidatesAtTail[block] = sinkCandidates; >+ changed = true; >+ >+ for (BasicBlock* successorBlock : block->successors()) { >+ for (Node* sinkCandidate : sinkCandidates) { >+ if (!successorBlock->ssa->liveAtHead.contains(sinkCandidate)) >+ continue; >+ sinkCandidatesAtHead[successorBlock].add(sinkCandidate); >+ } >+ } >+ } >+ } while (changed); >+ >+ // A node is a sink candidate if it is in the sinkCandidatesAtTail of a block but not in >+ // the liveAtTail of that same block. >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ for (Node* sinkCandidate : sinkCandidatesAtTail[block]) { >+ if (!block->ssa->liveAtTail.contains(sinkCandidate)) >+ m_sinkCandidates.add(sinkCandidate); >+ } >+ } >+ } >+ >+ void determineMaterializationPoints() >+ { >+ // The premise of this pass is that if there exists a point in the program where some >+ // path from a phantom allocation site to that point causes materialization, then *all* >+ // paths cause materialization. This should mean that there are never any redundant >+ // materializations. >+ >+ m_edgeToMaterializationPoint.clear(); >+ >+ BlockMap<HashSet<Node*>> materializedAtHead; >+ BlockMap<HashSet<Node*>> materializedAtTail; >+ >+ bool changed; >+ do { >+ changed = false; >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ HashSet<Node*> materialized = materializedAtHead[block]; >+ for (Node* node : *block) { >+ handleNode( >+ node, >+ [&] () { }, >+ [&] (Node* escapee) { >+ if (m_sinkCandidates.contains(escapee)) >+ materialized.add(escapee); >+ }); >+ } >+ >+ if (materialized == materializedAtTail[block]) >+ continue; >+ >+ changed = true; >+ >+ for (BasicBlock* successorBlock : block->successors()) { >+ for (Node* materializee : materialized) { >+ if (!successorBlock->ssa->liveAtHead.contains(materializee)) >+ continue; >+ materializedAtHead[successorBlock].add(materializee); >+ } >+ } >+ } >+ } while (changed); >+ >+ // A materialization edge exists at any point where a node escapes but hasn't been >+ // materialized yet. >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ HashSet<Node*> materialized = materializedAtHead[block]; >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ >+ handleNode( >+ node, >+ [&] () { }, >+ [&] (Node* escapee) { >+ if (!m_sinkCandidates.contains(escapee)) >+ return; >+ >+ if (!materialized.add(escapee).isNewEntry) >+ return; >+ >+ m_edgeToMaterializationPoint.add( >+ std::make_pair(node, escapee), >+ createMaterialize(escapee, node->origin)); >+ }); >+ } >+ } >+ } >+ >+ void placeMaterializationPoints() >+ { >+ m_ssaCalculator.reset(); >+ >+ HashMap<Node*, SSACalculator::Variable*> nodeToVariable; >+ Vector<Node*> indexToNode; >+ >+ for (Node* node : m_sinkCandidates) { >+ SSACalculator::Variable* variable = m_ssaCalculator.newVariable(); >+ nodeToVariable.add(node, variable); >+ ASSERT(indexToNode.size() == variable->index()); >+ indexToNode.append(node); >+ } >+ >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ for (Node* node : *block) { >+ if (SSACalculator::Variable* variable = nodeToVariable.get(node)) >+ m_ssaCalculator.newDef(variable, block, node); >+ >+ m_graph.doToChildren( >+ node, >+ [&] (Edge edge) { >+ Node* materialize = >+ m_edgeToMaterializationPoint.get(std::make_pair(node, edge.node())); >+ if (!materialize) >+ return; >+ >+ m_ssaCalculator.newDef( >+ nodeToVariable.get(edge.node()), block, materialize); >+ }); >+ } >+ } >+ >+ m_ssaCalculator.computePhis( >+ [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* { >+ Node* allocation = indexToNode[variable->index()]; >+ if (!block->ssa->liveAtHead.contains(allocation)) >+ return nullptr; >+ >+ Node* phiNode = m_graph.addNode(allocation->prediction(), Phi, NodeOrigin()); >+ phiNode->mergeFlags(NodeResultJS); >+ return phiNode; >+ }); >+ >+ // Place Phis in the right places. Replace all uses of any allocation with the appropriate >+ // materialization. Create the appropriate Upsilon nodes. >+ LocalOSRAvailabilityCalculator availabilityCalculator; >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ HashMap<Node*, Node*> mapping; >+ >+ for (Node* candidate : block->ssa->liveAtHead) { >+ SSACalculator::Variable* variable = nodeToVariable.get(candidate); >+ if (!variable) >+ continue; >+ >+ SSACalculator::Def* def = m_ssaCalculator.reachingDefAtHead(block, variable); >+ if (!def) >+ continue; >+ >+ mapping.add(indexToNode[variable->index()], def->value()); >+ } >+ >+ availabilityCalculator.beginBlock(block); >+ for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) { >+ m_insertionSet.insert(0, phiDef->value()); >+ >+ Node* originalNode = indexToNode[phiDef->variable()->index()]; >+ insertOSRHintsForUpdate( >+ m_insertionSet, 0, availabilityCalculator.m_availability, originalNode, >+ phiDef->value()); >+ >+ mapping.add(originalNode, phiDef->value()); >+ } >+ >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ >+ m_graph.doToChildEdges( >+ node, >+ [&] (Edge edge) { >+ Node* materialize = m_edgeToMaterializationPoint.get( >+ std::make_pair(node, edge.node())); >+ if (materialize) { >+ m_insertionSet.insert(nodeIndex, materialize); >+ insertOSRHintsForUpdate( >+ m_insertionSet, nodeIndex, availabilityCalculator.m_availability, >+ edge.node(), materialize); >+ } >+ }); >+ >+ availabilityCalculator.executeNode(node); >+ >+ m_graph.doToChildEdges( >+ node, >+ [&] (Edge& edge) { >+ if (Node* materialize = mapping.get(edge.node())) >+ edge.setNode(materialize); >+ }); >+ } >+ >+ size_t upsilonInsertionPoint = block->size() - 1; >+ NodeOrigin upsilonOrigin = block->last()->origin; >+ for (BasicBlock* successorBlock : block->successors()) { >+ for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) { >+ Node* phiNode = phiDef->value(); >+ SSACalculator::Variable* variable = phiDef->variable(); >+ Node* allocation = indexToNode[variable->index()]; >+ >+ Node* originalIncoming = mapping.get(allocation); >+ Node* incoming; >+ if (originalIncoming == allocation) { >+ // If we have a Phi that combines materializations with the original >+ // phantom object, then the path with the phantom object must materialize. >+ >+ incoming = createMaterialize(allocation, upsilonOrigin); >+ m_insertionSet.insert(upsilonInsertionPoint, incoming); >+ insertOSRHintsForUpdate( >+ m_insertionSet, upsilonInsertionPoint, >+ availabilityCalculator.m_availability, originalIncoming, incoming); >+ } else >+ incoming = originalIncoming; >+ >+ Node* upsilon = m_insertionSet.insertNode( >+ upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin, >+ OpInfo(phiNode), incoming->defaultEdge()); >+ >+ if (originalIncoming == allocation) { >+ m_edgeToMaterializationPoint.add( >+ std::make_pair(upsilon, allocation), incoming); >+ } >+ } >+ } >+ >+ m_insertionSet.execute(block); >+ } >+ >+ // At this point we have dummy materialization nodes along with edges to them. This means >+ // that the part of the control flow graph that prefers to see actual object allocations >+ // is completely fixed up, except for the materializations themselves. >+ } >+ >+ void lowerNonReadingOperationsOnPhantomAllocations() >+ { >+ // Lower everything but reading operations on phantom allocations. We absolutely have to >+ // lower all writes so as to reveal them to the SSA calculator. We cannot lower reads >+ // because the whole point is that those go away completely. >+ >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ switch (node->op()) { >+ case PutByOffset: { >+ if (m_sinkCandidates.contains(node->child2().node())) >+ node->convertToPutByOffsetHint(); >+ break; >+ } >+ >+ case PutStructure: { >+ if (m_sinkCandidates.contains(node->child1().node())) { >+ Node* structure = m_insertionSet.insertConstant( >+ nodeIndex, node->origin, JSValue(node->transition()->next)); >+ node->convertToPutStructureHint(structure); >+ } >+ break; >+ } >+ >+ case NewObject: { >+ if (m_sinkCandidates.contains(node)) { >+ Node* structure = m_insertionSet.insertConstant( >+ nodeIndex + 1, node->origin, JSValue(node->structure())); >+ m_insertionSet.insertNode( >+ nodeIndex + 1, SpecNone, PutStructureHint, node->origin, >+ Edge(node, KnownCellUse), Edge(structure, KnownCellUse)); >+ node->convertToPhantomNewObject(); >+ } >+ break; >+ } >+ >+ case MaterializeNewObject: { >+ if (m_sinkCandidates.contains(node)) { >+ m_insertionSet.insertNode( >+ nodeIndex + 1, SpecNone, PutStructureHint, node->origin, >+ Edge(node, KnownCellUse), m_graph.varArgChild(node, 0)); >+ for (unsigned i = 0; i < node->objectMaterializationData().m_properties.size(); ++i) { >+ m_insertionSet.insertNode( >+ nodeIndex + 1, SpecNone, PutByOffsetHint, node->origin, >+ Edge(node, KnownCellUse),m_graph.varArgChild(node, i + 1)); >+ } >+ node->convertToPhantomNewObject(); >+ } >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ m_insertionSet.execute(block); >+ } >+ } >+ >+ void promoteSunkenFields() >+ { >+ // Henceforth when we encounter a materialization point, we will want to ask *who* it is >+ // a materialization for. Invert the map to be able to answer such questions. >+ m_materializationPointToEscapee.clear(); >+ for (auto pair : m_edgeToMaterializationPoint) >+ m_materializationPointToEscapee.add(pair.value, pair.key.second); >+ >+ // Collect the set of heap locations that we will be operating over. >+ HashSet<PromotedHeapLocation> locations; >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ for (Node* node : *block) { >+ promoteHeapAccess( >+ node, >+ [&] (PromotedHeapLocation location, Edge) { >+ locations.add(location); >+ }, >+ [&] (PromotedHeapLocation location) { >+ locations.add(location); >+ }); >+ } >+ } >+ >+ // Figure out which locations belong to which allocations. >+ m_locationsForAllocation.clear(); >+ for (PromotedHeapLocation location : locations) { >+ auto result = m_locationsForAllocation.add(location.base(), Vector<PromotedHeapLocation>()); >+ ASSERT(!result.iterator->value.contains(location)); >+ result.iterator->value.append(location); >+ } >+ >+ // For each sunken thingy, make sure we create Bottom values for all of its fields. >+ // Note that this has the hilarious slight inefficiency of creating redundant hints for >+ // things that were previously materializations. This should only impact compile times and >+ // not code quality, and it's necessary for soundness without some data structure hackage. >+ // For example, a MaterializeNewObject that we choose to sink may have new fields added to >+ // it conditionally. That would necessitate Bottoms. >+ Node* bottom = nullptr; >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ if (block == m_graph.block(0)) >+ bottom = m_insertionSet.insertNode(0, SpecNone, BottomValue, NodeOrigin()); >+ >+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { >+ Node* node = block->at(nodeIndex); >+ for (PromotedHeapLocation location : m_locationsForAllocation.get(node)) { >+ m_insertionSet.insert( >+ nodeIndex + 1, location.createHint(m_graph, node->origin, bottom)); >+ } >+ } >+ m_insertionSet.execute(block); >+ } >+ >+ m_ssaCalculator.reset(); >+ >+ // Collect the set of "variables" that we will be sinking. >+ m_locationToVariable.clear(); >+ m_indexToLocation.clear(); >+ for (PromotedHeapLocation location : locations) { >+ SSACalculator::Variable* variable = m_ssaCalculator.newVariable(); >+ m_locationToVariable.add(location, variable); >+ ASSERT(m_indexToLocation.size() == variable->index()); >+ m_indexToLocation.append(location); >+ } >+ >+ // Create Defs from the existing hints. >+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { >+ for (Node* node : *block) { >+ promoteHeapAccess( >+ node, >+ [&] (PromotedHeapLocation location, Edge value) { >+ SSACalculator::Variable* variable = m_locationToVariable.get(location); >+ m_ssaCalculator.newDef(variable, block, value.node()); >+ }, >+ [&] (PromotedHeapLocation) { }); >+ } >+ } >+ >+ // OMG run the SSA calculator to create Phis! >+ m_ssaCalculator.computePhis( >+ [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* { >+ PromotedHeapLocation location = m_indexToLocation[variable->index()]; >+ if (!block->ssa->liveAtHead.contains(location.base())) >+ return nullptr; >+ >+ Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, NodeOrigin()); >+ phiNode->mergeFlags(NodeResultJS); >+ return phiNode; >+ }); >+ >+ // Place Phis in the right places, replace all uses of any load with the appropriate >+ // value, and create the appropriate Upsilon nodes. >+ m_graph.clearReplacements(); >+ for (BasicBlock* block : m_graph.blocksInPreOrder()) { >+ // This mapping table is intended to be lazy. If something is omitted from the table, >+ // it means that there haven't been any local stores to that promoted heap location. >+ m_localMapping.clear(); >+ >+ // Insert the Phi functions that we had previously created. >+ for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(block)) { >+ PromotedHeapLocation location = m_indexToLocation[phiDef->variable()->index()]; >+ >+ m_insertionSet.insert( >+ 0, phiDef->value()); >+ m_insertionSet.insert( >+ 0, location.createHint(m_graph, NodeOrigin(), phiDef->value())); >+ m_localMapping.add(location, phiDef->value()); >+ } >+ >+ // Process the block and replace all uses of loads with the promoted value. >+ for (Node* node : *block) { >+ m_graph.performSubstitution(node); >+ >+ if (Node* escapee = m_materializationPointToEscapee.get(node)) >+ populateMaterialize(block, node, escapee); >+ >+ promoteHeapAccess( >+ node, >+ [&] (PromotedHeapLocation location, Edge value) { >+ m_localMapping.set(location, value.node()); >+ }, >+ [&] (PromotedHeapLocation location) { >+ node->replaceWith(resolve(block, location)); >+ }); >+ } >+ >+ // Gotta drop some Upsilons. >+ size_t upsilonInsertionPoint = block->size() - 1; >+ NodeOrigin upsilonOrigin = block->last()->origin; >+ for (BasicBlock* successorBlock : block->successors()) { >+ for (SSACalculator::Def* phiDef : m_ssaCalculator.phisForBlock(successorBlock)) { >+ Node* phiNode = phiDef->value(); >+ SSACalculator::Variable* variable = phiDef->variable(); >+ PromotedHeapLocation location = m_indexToLocation[variable->index()]; >+ Node* incoming = resolve(block, location); >+ >+ m_insertionSet.insertNode( >+ upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin, >+ OpInfo(phiNode), incoming->defaultEdge()); >+ } >+ } >+ >+ m_insertionSet.execute(block); >+ } >+ } >+ >+ Node* resolve(BasicBlock* block, PromotedHeapLocation location) >+ { >+ if (Node* result = m_localMapping.get(location)) >+ return result; >+ >+ // This implies that there is no local mapping. Find a non-local mapping. >+ SSACalculator::Def* def = m_ssaCalculator.nonLocalReachingDef( >+ block, m_locationToVariable.get(location)); >+ ASSERT(def); >+ ASSERT(def->value()); >+ m_localMapping.add(location, def->value()); >+ return def->value(); >+ } >+ >+ template<typename SinkCandidateFunctor, typename EscapeFunctor> >+ void handleNode( >+ Node* node, >+ const SinkCandidateFunctor& sinkCandidate, >+ const EscapeFunctor& escape) >+ { >+ switch (node->op()) { >+ case NewObject: >+ case MaterializeNewObject: >+ sinkCandidate(); >+ break; >+ >+ case CheckStructure: >+ case GetByOffset: >+ case MultiGetByOffset: >+ case PutStructure: >+ case GetGetterSetterByOffset: >+ case MovHint: >+ break; >+ >+ case PutByOffset: >+ escape(node->child3().node()); >+ break; >+ >+ case MultiPutByOffset: >+ // FIXME: In the future we should be able to handle this. It's just a matter of >+ // building the appropriate *Hint variant of this instruction, along with a >+ // PhantomStructureSelect node - since this transforms the Structure in a conditional >+ // way. >+ // https://bugs.webkit.org/show_bug.cgi?id=136924 >+ escape(node->child1().node()); >+ escape(node->child2().node()); >+ break; >+ >+ default: >+ m_graph.doToChildren( >+ node, >+ [&escape] (Edge edge) { >+ escape(edge.node()); >+ }); >+ break; >+ } >+ } >+ >+ Node* createMaterialize(Node* escapee, const NodeOrigin whereOrigin) >+ { >+ switch (escapee->op()) { >+ case NewObject: >+ case MaterializeNewObject: { >+ ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add(); >+ >+ Node* result = m_graph.addNode( >+ escapee->prediction(), Node::VarArg, MaterializeNewObject, >+ NodeOrigin( >+ escapee->origin.semantic, >+ whereOrigin.forExit), >+ OpInfo(data), OpInfo(), 0, 0); >+ return result; >+ } >+ >+ default: >+ DFG_CRASH(m_graph, escapee, "Bad escapee op"); >+ return nullptr; >+ } >+ } >+ >+ void populateMaterialize(BasicBlock* block, Node* node, Node* escapee) >+ { >+ switch (node->op()) { >+ case MaterializeNewObject: { >+ ObjectMaterializationData& data = node->objectMaterializationData(); >+ unsigned firstChild = m_graph.m_varArgChildren.size(); >+ >+ Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee); >+ >+ PromotedHeapLocation structure(StructurePLoc, escapee); >+ ASSERT(locations.contains(structure)); >+ >+ m_graph.m_varArgChildren.append(resolve(block, structure)); >+ >+ for (unsigned i = 0; i < locations.size(); ++i) { >+ switch (locations[i].kind()) { >+ case StructurePLoc: { >+ ASSERT(locations[i] == structure); >+ break; >+ } >+ >+ case NamedPropertyPLoc: { >+ Node* value = resolve(block, locations[i]); >+ if (value->op() == BottomValue) { >+ // We can skip Bottoms entirely. >+ break; >+ } >+ >+ data.m_properties.append(PhantomPropertyValue(locations[i].info())); >+ m_graph.m_varArgChildren.append(value); >+ break; >+ } >+ >+ default: >+ DFG_CRASH(m_graph, node, "Bad location kind"); >+ } >+ } >+ >+ node->children = AdjacencyList( >+ AdjacencyList::Variable, >+ firstChild, m_graph.m_varArgChildren.size() - firstChild); >+ break; >+ } >+ >+ default: >+ DFG_CRASH(m_graph, node, "Bad materialize op"); >+ break; >+ } >+ } >+ >+ SSACalculator m_ssaCalculator; >+ HashSet<Node*> m_sinkCandidates; >+ HashMap<std::pair<Node*, Node*>, Node*> m_edgeToMaterializationPoint; >+ HashMap<Node*, Node*> m_materializationPointToEscapee; >+ HashMap<Node*, Vector<PromotedHeapLocation>> m_locationsForAllocation; >+ HashMap<PromotedHeapLocation, SSACalculator::Variable*> m_locationToVariable; >+ Vector<PromotedHeapLocation> m_indexToLocation; >+ HashMap<PromotedHeapLocation, Node*> m_localMapping; >+ InsertionSet m_insertionSet; >+}; >+ >+bool performObjectAllocationSinking(Graph& graph) >+{ >+ SamplingRegion samplingRegion("DFG Object Allocation Sinking Phase"); >+ return runPhase<ObjectAllocationSinkingPhase>(graph); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.h (working copy) >@@ -0,0 +1,47 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGObjectAllocationSinkingPhase_h >+#define DFGObjectAllocationSinkingPhase_h >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+// Sinks object allocations down to their uses. This will sink the allocations over OSR exits, by >+// replacing all stores to those objects with store hints so that OSR exit can materialize the >+// object. This may sink allocations past returns, creating control flow paths along which the >+// objects are not allocated at all. Replaces all uses of the objects' fields with SSA data flow. >+ >+bool performObjectAllocationSinking(Graph&); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGObjectAllocationSinkingPhase_h >+ >Index: Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGObjectMaterializationData.cpp (working copy) >@@ -0,0 +1,63 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGObjectMaterializationData.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include <wtf/ListDump.h> >+ >+namespace JSC { namespace DFG { >+ >+void PhantomPropertyValue::dump(PrintStream& out) const >+{ >+ out.print("id", m_identifierNumber); >+} >+ >+void ObjectMaterializationData::dump(PrintStream& out) const >+{ >+ out.print("[", listDump(m_properties), "]"); >+} >+ >+float ObjectMaterializationData::oneWaySimilarityScore( >+ const ObjectMaterializationData& other) const >+{ >+ unsigned numHits = 0; >+ for (PhantomPropertyValue value : m_properties) { >+ if (other.m_properties.contains(value)) >+ numHits++; >+ } >+ return static_cast<float>(numHits) / static_cast<float>(m_properties.size()); >+} >+ >+float ObjectMaterializationData::similarityScore(const ObjectMaterializationData& other) const >+{ >+ return std::min(oneWaySimilarityScore(other), other.oneWaySimilarityScore(*this)); >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGObjectMaterializationData.h (working copy) >@@ -0,0 +1,75 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGObjectMaterializationData_h >+#define DFGObjectMaterializationData_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include <wtf/PrintStream.h> >+#include <wtf/Vector.h> >+ >+namespace JSC { namespace DFG { >+ >+struct PhantomPropertyValue { >+ PhantomPropertyValue() >+ : m_identifierNumber(UINT_MAX) >+ { >+ } >+ >+ PhantomPropertyValue(unsigned identifierNumber) >+ : m_identifierNumber(identifierNumber) >+ { >+ } >+ >+ unsigned m_identifierNumber; >+ >+ bool operator==(const PhantomPropertyValue& other) const >+ { >+ return m_identifierNumber == other.m_identifierNumber; >+ } >+ >+ void dump(PrintStream&) const; >+}; >+ >+struct ObjectMaterializationData { >+ // Determines the meaning of the passed nodes. >+ Vector<PhantomPropertyValue> m_properties; >+ >+ void dump(PrintStream&) const; >+ >+ // The fraction of my properties that the other data has. >+ float oneWaySimilarityScore(const ObjectMaterializationData&) const; >+ >+ // The minimum of the two possible one-way scores. >+ float similarityScore(const ObjectMaterializationData&) const; >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGObjectMaterializationData_h >+ >Index: Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp (working copy) >@@ -52,18 +52,7 @@ public: > ASSERT(m_graph.m_form == SSA); > > m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsHardPhantom | NodeRelevantToOSR); >- >- for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >- BasicBlock* block = m_graph.block(blockIndex); >- if (!block) >- continue; >- >- for (unsigned i = block->size(); i--;) { >- Node* node = block->at(i); >- if (node->op() == MovHint) >- node->child1()->mergeFlags(NodeRelevantToOSR); >- } >- } >+ m_graph.mergeRelevantToOSR(); > > for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { > BasicBlock* block = m_graph.block(blockIndex); >Index: Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp (working copy) >@@ -74,17 +74,7 @@ public: > } > } > >- for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { >- BasicBlock* block = m_graph.block(blockIndex); >- if (!block) >- continue; >- >- for (unsigned i = block->size(); i--;) { >- Node* node = block->at(i); >- if (node->op() == MovHint) >- node->child1()->mergeFlags(NodeRelevantToOSR); >- } >- } >+ m_graph.mergeRelevantToOSR(); > > for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { > BasicBlock* block = m_graph.block(blockIndex); >Index: Source/JavaScriptCore/dfg/DFGPhiChildren.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPhiChildren.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGPhiChildren.cpp (working copy) >@@ -0,0 +1,64 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGPhiChildren.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGGraph.h" >+ >+namespace JSC { namespace DFG { >+ >+PhiChildren::PhiChildren() >+{ >+} >+ >+PhiChildren::PhiChildren(Graph& graph) >+{ >+ for (BasicBlock* block : graph.blocksInNaturalOrder()) { >+ for (Node* node : *block) { >+ if (node->op() != Upsilon) >+ continue; >+ >+ m_children.add(node->phi(), List()).iterator->value.append(node); >+ } >+ } >+} >+ >+PhiChildren::~PhiChildren() >+{ >+} >+ >+const PhiChildren::List& PhiChildren::upsilonsOf(Node* node) const >+{ >+ ASSERT(node->op() == Phi); >+ return m_children.find(node)->value; >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGPhiChildren.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPhiChildren.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGPhiChildren.h (working copy) >@@ -0,0 +1,92 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGPhiChildren_h >+#define DFGPhiChildren_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGNode.h" >+#include <wtf/HashSet.h> >+#include <wtf/Vector.h> >+ >+namespace JSC { namespace DFG { >+ >+class Graph; >+ >+class PhiChildren { >+public: >+ typedef Vector<Node*, 3> List; >+ >+ PhiChildren(); >+ PhiChildren(Graph&); >+ ~PhiChildren(); >+ >+ // The list of Upsilons that point to the children of the Phi. >+ const List& upsilonsOf(Node*) const; >+ >+ template<typename Functor> >+ void forAllIncomingValues(Node* node, const Functor& functor) >+ { >+ for (Node* upsilon : upsilonsOf(node)) >+ functor(upsilon->child1().node()); >+ } >+ >+ // This walks the Phi graph. >+ template<typename Functor> >+ void forAllTransitiveIncomingValues(Node* node, const Functor& functor) >+ { >+ if (node->op() != Phi) { >+ functor(node); >+ return; >+ } >+ HashSet<Node*> seen; >+ Vector<Node*> worklist; >+ seen.add(node); >+ worklist.append(node); >+ while (!worklist.isEmpty()) { >+ Node* currentNode = worklist.takeLast(); >+ forAllIncomingValues( >+ currentNode, >+ [&] (Node* incomingNode) { >+ if (incomingNode->op() == Phi) { >+ if (seen.add(incomingNode).isNewEntry) >+ worklist.append(incomingNode); >+ } else >+ functor(incomingNode); >+ }); >+ } >+ } >+ >+private: >+ HashMap<Node*, List> m_children; >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGPhiChildren_h >+ >Index: Source/JavaScriptCore/dfg/DFGPlan.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPlan.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGPlan.cpp (working copy) >@@ -49,6 +49,7 @@ > #include "DFGLoopPreHeaderCreationPhase.h" > #include "DFGOSRAvailabilityAnalysisPhase.h" > #include "DFGOSREntrypointCreationPhase.h" >+#include "DFGObjectAllocationSinkingPhase.h" > #include "DFGPhantomCanonicalizationPhase.h" > #include "DFGPhantomRemovalPhase.h" > #include "DFGPredictionInjectionPhase.h" >@@ -325,11 +326,12 @@ Plan::CompilationPath Plan::compileInThr > performCFA(dfg); > performConstantFolding(dfg); > performPhantomCanonicalization(dfg); // Reduce the graph size a lot. >- if (performStrengthReduction(dfg)) { >+ if (performStrengthReduction(dfg) | performObjectAllocationSinking(dfg)) { > // State-at-tail and state-at-head will be invalid if we did strength reduction since > // it might increase live ranges. > performLivenessAnalysis(dfg); > performCFA(dfg); >+ performConstantFolding(dfg); > } > performLICM(dfg); > performPhantomCanonicalization(dfg); >Index: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (working copy) >@@ -560,7 +560,12 @@ private: > case DoubleConstant: > case Int52Constant: > case Identity: >- case BooleanToNumber: { >+ case BooleanToNumber: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: { > // This node should never be visible at this stage of compilation. It is > // inserted by fixup(), which follows this phase. > RELEASE_ASSERT_NOT_REACHED(); >Index: Source/JavaScriptCore/dfg/DFGPromoteHeapAccess.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPromoteHeapAccess.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGPromoteHeapAccess.h (working copy) >@@ -0,0 +1,90 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGPromoteHeapAccess_h >+#define DFGPromoteHeapAccess_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGNode.h" >+#include "DFGPromotedHeapLocation.h" >+ >+namespace JSC { namespace DFG { >+ >+// Note that the write functor is really the useful thing here. The read functor is only useful >+// for the object allocation sinking phase. >+template<typename WriteFunctor, typename ReadFunctor> >+void promoteHeapAccess(Node* node, const WriteFunctor& write, const ReadFunctor& read) >+{ >+ switch (node->op()) { >+ case CheckStructure: { >+ if (node->child1()->isPhantomObjectAllocation()) >+ read(PromotedHeapLocation(StructurePLoc, node->child1())); >+ break; >+ } >+ >+ case GetByOffset: >+ case GetGetterSetterByOffset: { >+ if (node->child2()->isPhantomObjectAllocation()) { >+ unsigned identifierNumber = node->storageAccessData().identifierNumber; >+ read(PromotedHeapLocation(NamedPropertyPLoc, node->child2(), identifierNumber)); >+ } >+ break; >+ } >+ >+ case MultiGetByOffset: { >+ if (node->child1()->isPhantomObjectAllocation()) { >+ unsigned identifierNumber = node->multiGetByOffsetData().identifierNumber; >+ read(PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identifierNumber)); >+ } >+ break; >+ } >+ >+ case PutStructureHint: { >+ ASSERT(node->child1()->isPhantomObjectAllocation()); >+ write(PromotedHeapLocation(StructurePLoc, node->child1()), node->child2()); >+ break; >+ } >+ >+ case PutByOffsetHint: { >+ ASSERT(node->child1()->isPhantomObjectAllocation()); >+ unsigned identifierNumber = node->identifierNumber(); >+ write( >+ PromotedHeapLocation(NamedPropertyPLoc, node->child1(), identifierNumber), >+ node->child2()); >+ break; >+ } >+ >+ default: >+ break; >+ } >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGPromoteHeapAccess_h >+ >Index: Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp (working copy) >@@ -0,0 +1,93 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "DFGPromotedHeapLocation.h" >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGGraph.h" >+ >+namespace JSC { namespace DFG { >+ >+void PromotedLocationDescriptor::dump(PrintStream& out) const >+{ >+ out.print(m_kind, "(", m_info, ")"); >+} >+ >+Node* PromotedHeapLocation::createHint(Graph& graph, NodeOrigin origin, Node* value) >+{ >+ switch (kind()) { >+ case StructurePLoc: >+ return graph.addNode( >+ SpecNone, PutStructureHint, origin, >+ Edge(base(), KnownCellUse), Edge(value, KnownCellUse)); >+ >+ case NamedPropertyPLoc: >+ return graph.addNode( >+ SpecNone, PutByOffsetHint, origin, >+ OpInfo(info()), Edge(base(), KnownCellUse), Edge(value, UntypedUse)); >+ >+ case InvalidPromotedLocationKind: >+ return nullptr; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+void PromotedHeapLocation::dump(PrintStream& out) const >+{ >+ out.print(kind(), "(", m_base, ", ", info(), ")"); >+} >+ >+} } // namespace JSC::DFG >+ >+namespace WTF { >+ >+using namespace JSC::DFG; >+ >+void printInternal(PrintStream& out, PromotedLocationKind kind) >+{ >+ switch (kind) { >+ case InvalidPromotedLocationKind: >+ out.print("InvalidPromotedLocationKind"); >+ return; >+ >+ case StructurePLoc: >+ out.print("StructurePLoc"); >+ return; >+ >+ case NamedPropertyPLoc: >+ out.print("NamedPropertyPLoc"); >+ return; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace WTF; >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h (working copy) >@@ -0,0 +1,172 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 DFGPromotedHeapLocation_h >+#define DFGPromotedHeapLocation_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGNode.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace DFG { >+ >+enum PromotedLocationKind { >+ InvalidPromotedLocationKind, >+ >+ StructurePLoc, >+ NamedPropertyPLoc >+}; >+ >+class PromotedLocationDescriptor { >+public: >+ PromotedLocationDescriptor( >+ PromotedLocationKind kind = InvalidPromotedLocationKind, unsigned info = 0) >+ : m_kind(kind) >+ , m_info(info) >+ { >+ } >+ >+ bool operator!() const { return m_kind == InvalidPromotedLocationKind; } >+ >+ PromotedLocationKind kind() const { return m_kind; } >+ unsigned info() const { return m_info; } >+ >+ unsigned hash() const >+ { >+ return m_kind + m_info; >+ } >+ >+ bool operator==(const PromotedLocationDescriptor& other) const >+ { >+ return m_kind == other.m_kind >+ && m_info == other.m_info; >+ } >+ >+ bool operator!=(const PromotedLocationDescriptor& other) const >+ { >+ return !(*this == other); >+ } >+ >+ bool isHashTableDeletedValue() const >+ { >+ return m_kind == InvalidPromotedLocationKind && m_info; >+ } >+ >+ void dump(PrintStream& out) const; >+ >+private: >+ PromotedLocationKind m_kind; >+ unsigned m_info; >+}; >+ >+class PromotedHeapLocation { >+public: >+ PromotedHeapLocation( >+ PromotedLocationKind kind = InvalidPromotedLocationKind, >+ Node* base = nullptr, unsigned info = 0) >+ : m_base(base) >+ , m_meta(kind, info) >+ { >+ } >+ >+ PromotedHeapLocation( >+ PromotedLocationKind kind, Edge base, unsigned info = 0) >+ : PromotedHeapLocation(kind, base.node(), info) >+ { >+ } >+ >+ PromotedHeapLocation(Node* base, PromotedLocationDescriptor meta) >+ : m_base(base) >+ , m_meta(meta) >+ { >+ } >+ >+ PromotedHeapLocation(WTF::HashTableDeletedValueType) >+ : m_base(nullptr) >+ , m_meta(InvalidPromotedLocationKind, 1) >+ { >+ } >+ >+ Node* createHint(Graph&, NodeOrigin, Node* value); >+ >+ bool operator!() const { return kind() == InvalidPromotedLocationKind; } >+ >+ PromotedLocationKind kind() const { return m_meta.kind(); } >+ Node* base() const { return m_base; } >+ unsigned info() const { return m_meta.info(); } >+ PromotedLocationDescriptor descriptor() const { return m_meta; } >+ >+ unsigned hash() const >+ { >+ return m_meta.hash() + WTF::PtrHash<Node*>::hash(m_base); >+ } >+ >+ bool operator==(const PromotedHeapLocation& other) const >+ { >+ return m_base == other.m_base >+ && m_meta == other.m_meta; >+ } >+ >+ bool isHashTableDeletedValue() const >+ { >+ return m_meta.isHashTableDeletedValue(); >+ } >+ >+ void dump(PrintStream& out) const; >+ >+private: >+ Node* m_base; >+ PromotedLocationDescriptor m_meta; >+}; >+ >+struct PromotedHeapLocationHash { >+ static unsigned hash(const PromotedHeapLocation& key) { return key.hash(); } >+ static bool equal(const PromotedHeapLocation& a, const PromotedHeapLocation& b) { return a == b; } >+ static const bool safeToCompareToEmptyOrDeleted = true; >+}; >+ >+} } // namespace JSC::DFG >+ >+namespace WTF { >+ >+void printInternal(PrintStream&, JSC::DFG::PromotedLocationKind); >+ >+template<typename T> struct DefaultHash; >+template<> struct DefaultHash<JSC::DFG::PromotedHeapLocation> { >+ typedef JSC::DFG::PromotedHeapLocationHash Hash; >+}; >+ >+template<typename T> struct HashTraits; >+template<> struct HashTraits<JSC::DFG::PromotedHeapLocation> : SimpleClassHashTraits<JSC::DFG::PromotedHeapLocation> { >+ static const bool emptyValueIsZero = false; >+}; >+ >+} // namespace WTF >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGPromotedHeapLocation_h >+ >Index: Source/JavaScriptCore/dfg/DFGSSACalculator.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSSACalculator.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGSSACalculator.cpp (working copy) >@@ -66,6 +66,17 @@ SSACalculator::~SSACalculator() > { > } > >+void SSACalculator::reset() >+{ >+ m_variables.clear(); >+ m_defs.clear(); >+ m_phis.clear(); >+ for (BlockIndex blockIndex = m_data.size(); blockIndex--;) { >+ m_data[blockIndex].m_defs.clear(); >+ m_data[blockIndex].m_phis.clear(); >+ } >+} >+ > SSACalculator::Variable* SSACalculator::newVariable() > { > return &m_variables.alloc(Variable(m_variables.size())); >Index: Source/JavaScriptCore/dfg/DFGSSACalculator.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSSACalculator.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGSSACalculator.h (working copy) >@@ -105,6 +105,8 @@ public: > SSACalculator(Graph&); > ~SSACalculator(); > >+ void reset(); >+ > class Variable { > public: > unsigned index() const { return m_index; } >Index: Source/JavaScriptCore/dfg/DFGSafeToExecute.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSafeToExecute.h (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGSafeToExecute.h (working copy) >@@ -270,6 +270,11 @@ bool safeToExecute(AbstractStateType& st > case GetGenericPropertyEnumerator: > case GetEnumeratorPname: > case ToIndexString: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: > return true; > > case NativeCall: >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (working copy) >@@ -4912,6 +4912,11 @@ void SpeculativeJIT::compile(Node* node) > case NativeConstruct: > case CheckBadCell: > case BottomValue: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: > RELEASE_ASSERT_NOT_REACHED(); > break; > } >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 173837) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4982,6 +4982,11 @@ void SpeculativeJIT::compile(Node* node) > case FiatInt52: > case CheckBadCell: > case BottomValue: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: > DFG_CRASH(m_jit.graph(), node, "Unexpected node"); > break; > } >Index: Source/JavaScriptCore/ftl/FTLCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLCapabilities.cpp (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLCapabilities.cpp (working copy) >@@ -168,6 +168,11 @@ inline CapabilityLevel canCompile(Node* > case GetEnumeratorPname: > case ToIndexString: > case BottomValue: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case CheckStructureImmediate: >+ case PutStructureHint: >+ case MaterializeNewObject: > // These are OK. > break; > case ProfiledCall: >Index: Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "FTLExitPropertyValue.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+void ExitPropertyValue::dump(PrintStream& out) const >+{ >+ out.print(m_location, " => ", m_value); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitPropertyValue.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitPropertyValue.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitPropertyValue.h (working copy) >@@ -0,0 +1,66 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 FTLExitPropertyValue_h >+#define FTLExitPropertyValue_h >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGPromotedHeapLocation.h" >+#include "FTLExitValue.h" >+ >+namespace JSC { namespace FTL { >+ >+class ExitPropertyValue { >+public: >+ ExitPropertyValue() >+ { >+ } >+ >+ ExitPropertyValue(DFG::PromotedLocationDescriptor location, const ExitValue& value) >+ : m_location(location) >+ , m_value(value) >+ { >+ ASSERT(!!location == !!value); >+ } >+ >+ bool operator!() const { return !m_location; } >+ >+ DFG::PromotedLocationDescriptor location() const { return m_location; } >+ const ExitValue& value() const { return m_value; } >+ >+ void dump(PrintStream& out) const; >+ >+private: >+ DFG::PromotedLocationDescriptor m_location; >+ ExitValue m_value; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitPropertyValue_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp (working copy) >@@ -0,0 +1,69 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "FTLExitTimeObjectMaterialization.h" >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGGraph.h" >+ >+namespace JSC { namespace FTL { >+ >+using namespace JSC::DFG; >+ >+ExitTimeObjectMaterialization::ExitTimeObjectMaterialization(NodeType type) >+ : m_type(type) >+{ >+} >+ >+ExitTimeObjectMaterialization::~ExitTimeObjectMaterialization() >+{ >+} >+ >+void ExitTimeObjectMaterialization::add( >+ PromotedLocationDescriptor location, const ExitValue& value) >+{ >+ m_properties.append(ExitPropertyValue(location, value)); >+} >+ >+ExitValue ExitTimeObjectMaterialization::get(PromotedLocationDescriptor location) const >+{ >+ for (ExitPropertyValue value : m_properties) { >+ if (value.location() == location) >+ return value.value(); >+ } >+ return ExitValue(); >+} >+ >+void ExitTimeObjectMaterialization::dump(PrintStream& out) const >+{ >+ out.print(RawPointer(this), ":", Graph::opName(m_type), "(", listDump(m_properties), ")"); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h (working copy) >@@ -0,0 +1,63 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 FTLExitTimeObjectMaterialization_h >+#define FTLExitTimeObjectMaterialization_h >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGNodeType.h" >+#include "FTLExitPropertyValue.h" >+#include "FTLExitValue.h" >+#include <wtf/Noncopyable.h> >+ >+namespace JSC { namespace FTL { >+ >+class ExitTimeObjectMaterialization { >+ WTF_MAKE_NONCOPYABLE(ExitTimeObjectMaterialization) >+public: >+ ExitTimeObjectMaterialization(DFG::NodeType); >+ ~ExitTimeObjectMaterialization(); >+ >+ void add(DFG::PromotedLocationDescriptor, const ExitValue&); >+ >+ DFG::NodeType type() const { return m_type; } >+ >+ ExitValue get(DFG::PromotedLocationDescriptor) const; >+ const Vector<ExitPropertyValue>& properties() const { return m_properties; } >+ >+ void dump(PrintStream& out) const; >+ >+private: >+ DFG::NodeType m_type; >+ Vector<ExitPropertyValue> m_properties; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitTimeObjectMaterialization_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitValue.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitValue.cpp (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLExitValue.cpp (working copy) >@@ -28,10 +28,19 @@ > > #if ENABLE(FTL_JIT) > >+#include "FTLExitTimeObjectMaterialization.h" > #include "JSCInlines.h" > > namespace JSC { namespace FTL { > >+ExitValue ExitValue::materializeNewObject(ExitTimeObjectMaterialization* data) >+{ >+ ExitValue result; >+ result.m_kind = ExitValueMaterializeNewObject; >+ result.u.newObjectMaterializationData = data; >+ return result; >+} >+ > void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const > { > switch (kind()) { >@@ -65,6 +74,9 @@ void ExitValue::dumpInContext(PrintStrea > case ExitValueRecovery: > out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")"); > return; >+ case ExitValueMaterializeNewObject: >+ out.print("Materialize(", pointerDump(objectMaterialization()), ")"); >+ return; > } > > RELEASE_ASSERT_NOT_REACHED(); >Index: Source/JavaScriptCore/ftl/FTLExitValue.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitValue.h (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLExitValue.h (working copy) >@@ -52,9 +52,12 @@ enum ExitValueKind { > ExitValueInJSStackAsInt52, > ExitValueInJSStackAsDouble, > ExitValueArgumentsObjectThatWasNotCreated, >- ExitValueRecovery >+ ExitValueRecovery, >+ ExitValueMaterializeNewObject > }; > >+class ExitTimeObjectMaterialization; >+ > class ExitValue { > public: > ExitValue() >@@ -137,6 +140,8 @@ public: > return result; > } > >+ static ExitValue materializeNewObject(ExitTimeObjectMaterialization*); >+ > ExitValueKind kind() const { return m_kind; } > > bool isDead() const { return kind() == ExitValueDead; } >@@ -156,6 +161,7 @@ public: > bool isArgument() const { return kind() == ExitValueArgument; } > bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; } > bool isRecovery() const { return kind() == ExitValueRecovery; } >+ bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; } > > ExitArgument exitArgument() const > { >@@ -199,7 +205,13 @@ public: > return VirtualRegister(u.virtualRegister); > } > >- ExitValue withVirtualRegister(VirtualRegister virtualRegister) >+ ExitTimeObjectMaterialization* objectMaterialization() const >+ { >+ ASSERT(isObjectMaterialization()); >+ return u.newObjectMaterializationData; >+ } >+ >+ ExitValue withVirtualRegister(VirtualRegister virtualRegister) const > { > ASSERT(isInJSStackSomehow()); > ExitValue result; >@@ -207,7 +219,7 @@ public: > result.u.virtualRegister = virtualRegister.offset(); > return result; > } >- >+ > // If it's in the JSStack somehow, this will tell you what format it's in, in a manner > // that is compatible with exitArgument().format(). If it's a constant or it's dead, it > // will claim to be a JSValue. If it's an argument then it will tell you the argument's >@@ -223,6 +235,7 @@ public: > case ExitValueConstant: > case ExitValueInJSStack: > case ExitValueArgumentsObjectThatWasNotCreated: >+ case ExitValueMaterializeNewObject: > return ValueFormatJSValue; > > case ExitValueArgument: >@@ -260,6 +273,7 @@ private: > uint16_t opcode; > uint16_t format; > } recovery; >+ ExitTimeObjectMaterialization* newObjectMaterializationData; > } u; > }; > >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -38,6 +38,7 @@ > #include "FTLFormattedValue.h" > #include "FTLInlineCacheSize.h" > #include "FTLLoweredNodeValue.h" >+#include "FTLOperations.h" > #include "FTLOutput.h" > #include "FTLThunks.h" > #include "FTLWeightedTarget.h" >@@ -725,6 +726,12 @@ private: > case ToIndexString: > compileToIndexString(); > break; >+ case CheckStructureImmediate: >+ compileCheckStructureImmediate(); >+ break; >+ case MaterializeNewObject: >+ compileMaterializeNewObject(); >+ break; > > case PhantomLocal: > case SetArgument: >@@ -735,6 +742,9 @@ private: > case AllocationProfileWatchpoint: > case MovHint: > case ZombieHint: >+ case PhantomNewObject: >+ case PutByOffsetHint: >+ case PutStructureHint: > break; > default: > DFG_CRASH(m_graph, m_node, "Unrecognized node in FTL backend"); >@@ -1704,30 +1714,7 @@ private: > > LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID); > >- if (m_node->structureSet().size() == 1) { >- speculate( >- exitKind, jsValueValue(cell), 0, >- m_out.notEqual(structureID, weakStructure(m_node->structureSet()[0]))); >- return; >- } >- >- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation")); >- >- LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation); >- for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) { >- LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure")); >- m_out.branch( >- m_out.equal(structureID, weakStructure(m_node->structureSet()[i])), >- unsure(continuation), unsure(nextStructure)); >- m_out.appendTo(nextStructure); >- } >- >- speculate( >- exitKind, jsValueValue(cell), 0, >- m_out.notEqual(structureID, weakStructure(m_node->structureSet().last()))); >- >- m_out.jump(continuation); >- m_out.appendTo(continuation, lastNext); >+ checkStructure(structureID, jsValueValue(cell), exitKind, m_node->structureSet()); > } > > void compileCheckCell() >@@ -2649,28 +2636,7 @@ private: > > void compileNewObject() > { >- Structure* structure = m_node->structure(); >- size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); >- MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize); >- >- LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("NewObject slow path")); >- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewObject continuation")); >- >- LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); >- >- ValueFromBlock fastResult = m_out.anchor(allocateObject( >- m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath)); >- >- m_out.jump(continuation); >- >- m_out.appendTo(slowPath, continuation); >- >- ValueFromBlock slowResult = m_out.anchor(vmCall( >- m_out.operation(operationNewObject), m_callFrame, m_out.constIntPtr(structure))); >- m_out.jump(continuation); >- >- m_out.appendTo(continuation, lastNext); >- setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); >+ setJSValue(allocateObject(m_node->structure())); > } > > void compileNewArray() >@@ -3370,7 +3336,7 @@ private: > LBasicBlock lastNext = m_out.m_nextBlock; > > for (unsigned i = data.variants.size(); i--;) { >- m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit); >+ m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit); > > PutByIdVariant variant = data.variants[i]; > >@@ -3953,12 +3919,13 @@ private: > void compileInvalidationPoint() > { > if (verboseCompilationEnabled()) >- dataLog(" Invalidation point with availability: ", availability(), "\n"); >+ dataLog(" Invalidation point with availability: ", availabilityMap(), "\n"); > > m_ftlState.jitCode->osrExit.append(OSRExit( > UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(), > m_codeOriginForExitTarget, m_codeOriginForExitProfile, >- availability().numberOfArguments(), availability().numberOfLocals())); >+ availabilityMap().m_locals.numberOfArguments(), >+ availabilityMap().m_locals.numberOfLocals())); > m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo()); > > OSRExit& exit = m_ftlState.jitCode->osrExit.last(); >@@ -4360,6 +4327,122 @@ private: > LValue index = lowInt32(m_node->child1()); > setJSValue(vmCall(m_out.operation(operationToIndexString), m_callFrame, index)); > } >+ >+ void compileCheckStructureImmediate() >+ { >+ LValue structureID = lowCell(m_node->child1()); >+ checkStructure(structureID, noValue(), BadCache, m_node->structureSet()); >+ } >+ >+ void compileMaterializeNewObject() >+ { >+ ObjectMaterializationData& data = m_node->objectMaterializationData(); >+ >+ // Lower the values first, to avoid creating values inside a control flow diamond. >+ >+ Vector<LValue, 8> values; >+ for (unsigned i = 0; i < data.m_properties.size(); ++i) >+ values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i))); >+ >+ StructureSet set; >+ m_interpreter.phiChildren()->forAllTransitiveIncomingValues( >+ m_node, >+ [&] (Node* incoming) { >+ Structure* structure = incoming->dynamicCastConstant<Structure*>(); >+ DFG_ASSERT(m_graph, m_node, structure); >+ set.add(structure); >+ }); >+ >+ Vector<LBasicBlock, 1> blocks(set.size()); >+ for (unsigned i = set.size(); i--;) >+ blocks[i] = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject case ", i)); >+ LBasicBlock dummyDefault = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject default case")); >+ LBasicBlock outerContinuation = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject continuation")); >+ >+ Vector<SwitchCase, 1> cases(set.size()); >+ for (unsigned i = set.size(); i--;) >+ cases[i] = SwitchCase(weakStructure(set[i]), blocks[i], Weight(1)); >+ m_out.switchInstruction( >+ lowCell(m_graph.varArgChild(m_node, 0)), cases, dummyDefault, Weight(0)); >+ >+ LBasicBlock outerLastNext = m_out.m_nextBlock; >+ >+ Vector<ValueFromBlock, 1> results; >+ >+ for (unsigned i = set.size(); i--;) { >+ m_out.appendTo(blocks[i], i + 1 < set.size() ? blocks[i + 1] : dummyDefault); >+ >+ Structure* structure = set[i]; >+ >+ LValue object; >+ LValue butterfly; >+ >+ if (structure->outOfLineCapacity()) { >+ size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); >+ MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize); >+ >+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject complex object allocation slow path")); >+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MaterializeNewObject complex object allocation continuation")); >+ >+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); >+ >+ LValue endOfStorage = allocateBasicStorageAndGetEnd( >+ m_out.constIntPtr(structure->outOfLineCapacity() * sizeof(JSValue)), >+ slowPath); >+ >+ LValue fastButterflyValue = m_out.add( >+ m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage); >+ >+ LValue fastObjectValue = allocateObject( >+ m_out.constIntPtr(allocator), structure, fastButterflyValue, slowPath); >+ >+ ValueFromBlock fastObject = m_out.anchor(fastObjectValue); >+ ValueFromBlock fastButterfly = m_out.anchor(fastButterflyValue); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(slowPath, continuation); >+ >+ ValueFromBlock slowObject = m_out.anchor(vmCall( >+ m_out.operation(operationNewObjectWithButterfly), >+ m_callFrame, m_out.constIntPtr(structure))); >+ ValueFromBlock slowButterfly = m_out.anchor( >+ m_out.loadPtr(slowObject.value(), m_heaps.JSObject_butterfly)); >+ >+ m_out.jump(continuation); >+ >+ m_out.appendTo(continuation, lastNext); >+ >+ object = m_out.phi(m_out.intPtr, fastObject, slowObject); >+ butterfly = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); >+ } else { >+ // In the easy case where we can do a one-shot allocation, we simply allocate the >+ // object to directly have the desired structure. >+ object = allocateObject(structure); >+ butterfly = nullptr; // Don't have one, don't need one. >+ } >+ >+ for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) { >+ for (unsigned i = data.m_properties.size(); i--;) { >+ PhantomPropertyValue value = data.m_properties[i]; >+ if (m_graph.identifiers()[value.m_identifierNumber] != entry.key) >+ continue; >+ >+ LValue base = isInlineOffset(entry.offset) ? object : butterfly; >+ storeProperty(values[i], base, value.m_identifierNumber, entry.offset); >+ break; >+ } >+ } >+ >+ results.append(m_out.anchor(object)); >+ m_out.jump(outerContinuation); >+ } >+ >+ m_out.appendTo(dummyDefault, outerContinuation); >+ m_out.unreachable(); >+ >+ m_out.appendTo(outerContinuation, outerLastNext); >+ setJSValue(m_out.phi(m_out.intPtr, results)); >+ } > > #if ENABLE(FTL_NATIVE_CALL_INLINING) > LValue getFunctionBySymbol(const CString symbol) >@@ -4525,6 +4608,36 @@ private: > return m_out.booleanFalse; > } > >+ void checkStructure( >+ LValue structureID, const FormattedValue& formattedValue, ExitKind exitKind, >+ const StructureSet& set) >+ { >+ if (set.size() == 1) { >+ speculate( >+ exitKind, formattedValue, 0, >+ m_out.notEqual(structureID, weakStructure(set[0]))); >+ return; >+ } >+ >+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkStructure continuation")); >+ >+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation); >+ for (unsigned i = 0; i < set.size() - 1; ++i) { >+ LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("checkStructure nextStructure")); >+ m_out.branch( >+ m_out.equal(structureID, weakStructure(set[i])), >+ unsure(continuation), unsure(nextStructure)); >+ m_out.appendTo(nextStructure); >+ } >+ >+ speculate( >+ exitKind, formattedValue, 0, >+ m_out.notEqual(structureID, weakStructure(set.last()))); >+ >+ m_out.jump(continuation); >+ m_out.appendTo(continuation, lastNext); >+ } >+ > LValue numberOrNotCellToInt32(Edge edge, LValue value) > { > LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 int case")); >@@ -4624,84 +4737,74 @@ private: > m_callFrame, object); > } > >- LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage slow path")); >- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage continuation")); >- >- LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); >- >- LValue endOfStorage = allocateBasicStorageAndGetEnd( >- m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath); >- >- ValueFromBlock fastButterfly = m_out.anchor( >- m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage)); >- >- m_out.jump(continuation); >- >- m_out.appendTo(slowPath, continuation); >- >- ValueFromBlock slowButterfly = m_out.anchor(vmCall( >- m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame)); >- >- m_out.jump(continuation); >- >- m_out.appendTo(continuation, lastNext); >- >- LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); >+ LValue result = allocatePropertyStorageWithSizeImpl(initialOutOfLineCapacity); > m_out.storePtr(result, object, m_heaps.JSObject_butterfly); >- > return result; > } > > LValue reallocatePropertyStorage( > LValue object, LValue oldStorage, Structure* previous, Structure* next) > { >- size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue); >+ size_t oldSize = previous->outOfLineCapacity(); > size_t newSize = oldSize * outOfLineGrowthFactor; > >- ASSERT_UNUSED(next, newSize == next->outOfLineCapacity() * sizeof(JSValue)); >+ ASSERT_UNUSED(next, newSize == next->outOfLineCapacity()); > > if (previous->couldHaveIndexingHeader()) { >- LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue)); >+ LValue newAllocSize = m_out.constIntPtr(newSize); > return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize); > } > >- LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage slow path")); >- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage continuation")); >+ LValue result = allocatePropertyStorageWithSizeImpl(newSize); >+ >+ ptrdiff_t headerSize = -sizeof(IndexingHeader) - sizeof(void*); >+ ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize * sizeof(JSValue)); >+ >+ for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) { >+ LValue loaded = >+ m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset)); >+ m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset)); >+ } >+ >+ m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly)); >+ >+ return result; >+ } >+ >+ LValue allocatePropertyStorageWithSizeImpl(size_t sizeInValues) >+ { >+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorageWithSizeImpl slow path")); >+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorageWithSizeImpl continuation")); >+ > LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); > >- LValue endOfStorage = >- allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath); >+ LValue endOfStorage = allocateBasicStorageAndGetEnd( >+ m_out.constIntPtr(sizeInValues * sizeof(JSValue)), slowPath); > >- ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage)); >+ ValueFromBlock fastButterfly = m_out.anchor( >+ m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage)); > > m_out.jump(continuation); > > m_out.appendTo(slowPath, continuation); > >- LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue)); >- >- LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize); >- >- ValueFromBlock slowButterfly = m_out.anchor(storageLocation); >+ LValue slowButterflyValue; >+ if (sizeInValues == initialOutOfLineCapacity) { >+ slowButterflyValue = vmCall( >+ m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), >+ m_callFrame); >+ } else { >+ slowButterflyValue = vmCall( >+ m_out.operation(operationAllocatePropertyStorage), >+ m_callFrame, m_out.constIntPtr(sizeInValues)); >+ } >+ ValueFromBlock slowButterfly = m_out.anchor(slowButterflyValue); > > m_out.jump(continuation); > > m_out.appendTo(continuation, lastNext); > >- LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); >- >- ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *); >- ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize); >- >- for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) { >- LValue loaded = >- m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset)); >- m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset)); >- } >- >- m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly)); >- >- return result; >+ return m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); > } > > LValue getById(LValue base) >@@ -4841,7 +4944,7 @@ private: > setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult)); > } > >- LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath) >+ LValue allocateCell(LValue allocator, LBasicBlock slowPath) > { > LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success")); > >@@ -4856,12 +4959,21 @@ private: > m_out.loadPtr(result, m_heaps.JSCell_freeListNext), > allocator, m_heaps.MarkedAllocator_freeListHead); > >- m_out.store32(m_out.constInt32(structure->id()), result, m_heaps.JSCell_structureID); >- >+ return result; >+ } >+ >+ void storeStructure(LValue object, Structure* structure) >+ { >+ m_out.store32(m_out.constInt32(structure->id()), object, m_heaps.JSCell_structureID); > m_out.store32( > m_out.constInt32(structure->objectInitializationBlob()), >- result, m_heaps.JSCell_usefulBytes); >- >+ object, m_heaps.JSCell_usefulBytes); >+ } >+ >+ LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath) >+ { >+ LValue result = allocateCell(allocator, slowPath); >+ storeStructure(result, structure); > return result; > } > >@@ -4908,6 +5020,31 @@ private: > m_out.loadPtr(m_out.absolute(&allocator.m_currentPayloadEnd)), newRemaining); > } > >+ LValue allocateObject(Structure* structure) >+ { >+ size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); >+ MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize); >+ >+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocateObject slow path")); >+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocateObject continuation")); >+ >+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); >+ >+ ValueFromBlock fastResult = m_out.anchor(allocateObject( >+ m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath)); >+ >+ m_out.jump(continuation); >+ >+ m_out.appendTo(slowPath, continuation); >+ >+ ValueFromBlock slowResult = m_out.anchor(vmCall( >+ m_out.operation(operationNewObject), m_callFrame, m_out.constIntPtr(structure))); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(continuation, lastNext); >+ return m_out.phi(m_out.intPtr, fastResult, slowResult); >+ } >+ > struct ArrayValues { > ArrayValues() > : array(0) >@@ -6344,7 +6481,7 @@ private: > ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) > { > if (verboseCompilationEnabled()) { >- dataLog(" OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availability(), "\n"); >+ dataLog(" OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", availabilityMap(), "\n"); > if (!m_availableRecoveries.isEmpty()) > dataLog(" Available recoveries: ", listDump(m_availableRecoveries), "\n"); > } >@@ -6354,7 +6491,8 @@ private: > m_ftlState.jitCode->osrExit.append(OSRExit( > kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue), > m_codeOriginForExitTarget, m_codeOriginForExitProfile, >- availability().numberOfArguments(), availability().numberOfLocals())); >+ availabilityMap().m_locals.numberOfArguments(), >+ availabilityMap().m_locals.numberOfLocals())); > m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo()); > > OSRExit& exit = m_ftlState.jitCode->osrExit.last(); >@@ -6394,56 +6532,52 @@ private: > if (!!lowValue) > arguments.append(lowValue.value()); > >+ AvailabilityMap availabilityMap = this->availabilityMap(); >+ > for (unsigned i = 0; i < exit.m_values.size(); ++i) { > int operand = exit.m_values.operandForIndex(i); >- bool isLive = m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin); >- if (!isLive) { >- exit.m_values[i] = ExitValue::dead(); >- continue; >- } >- >- Availability availability = this->availability()[i]; >- FlushedAt flush = availability.flushedAt(); >- switch (flush.format()) { >- case DeadFlush: >- case ConflictingFlush: >- if (availability.hasNode()) { >- exit.m_values[i] = exitValueForNode(arguments, availability.node()); >- break; >- } >- >- if (Options::validateFTLOSRExitLiveness()) >- DFG_CRASH(m_graph, m_node, toCString("Expected r", operand, " to be available but it wasn't.").data()); >- >- // This means that the DFG's DCE proved that the value is dead in bytecode >- // even though the bytecode liveness analysis thinks it's live. This is >- // acceptable since the DFG's DCE is by design more aggressive while still >- // being sound. >- exit.m_values[i] = ExitValue::dead(); >- break; >- >- case FlushedJSValue: >- case FlushedCell: >- case FlushedBoolean: >- exit.m_values[i] = ExitValue::inJSStack(flush.virtualRegister()); >- break; >- >- case FlushedInt32: >- exit.m_values[i] = ExitValue::inJSStackAsInt32(flush.virtualRegister()); >- break; >- >- case FlushedInt52: >- exit.m_values[i] = ExitValue::inJSStackAsInt52(flush.virtualRegister()); >- break; >+ if (!m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin)) >+ availabilityMap.m_locals[i] = Availability(); >+ } >+ >+ availabilityMap.prune(); >+ >+ HashMap<Node*, ExitTimeObjectMaterialization*> map; >+ availabilityMap.forEachAvailability( >+ [&] (Availability availability) { >+ if (!availability.shouldUseNode()) >+ return; > >- case FlushedDouble: >- exit.m_values[i] = ExitValue::inJSStackAsDouble(flush.virtualRegister()); >- break; >+ Node* node = availability.node(); >+ if (!node->isPhantomObjectAllocation()) >+ return; > >- case FlushedArguments: >- exit.m_values[i] = ExitValue::argumentsObjectThatWasNotCreated(); >- break; >+ auto result = map.add(node, nullptr); >+ if (result.isNewEntry) >+ result.iterator->value = exit.m_materializations.add(node->op()); >+ }); >+ >+ for (unsigned i = 0; i < exit.m_values.size(); ++i) { >+ int operand = exit.m_values.operandForIndex(i); >+ >+ Availability availability = this->availabilityMap().m_locals[i]; >+ >+ if (Options::validateFTLOSRExitLiveness()) { >+ DFG_ASSERT( >+ m_graph, m_node, >+ m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin) >+ == availability.isDead()); > } >+ >+ exit.m_values[i] = exitValueForAvailability(arguments, map, availability); >+ } >+ >+ for (auto heapPair : availabilityMap.m_heap) { >+ Node* node = heapPair.key.base(); >+ ExitTimeObjectMaterialization* materialization = map.get(node); >+ materialization->add( >+ heapPair.key.descriptor(), >+ exitValueForAvailability(arguments, map, heapPair.value)); > } > > if (verboseCompilationEnabled()) >@@ -6459,13 +6593,57 @@ private: > m_out.call(m_out.stackmapIntrinsic(), arguments); > } > >- ExitValue exitValueForNode(ExitArgumentList& arguments, Node* node) >+ ExitValue exitValueForAvailability( >+ ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map, >+ Availability availability) >+ { >+ FlushedAt flush = availability.flushedAt(); >+ switch (flush.format()) { >+ case DeadFlush: >+ case ConflictingFlush: >+ if (availability.hasNode()) >+ return exitValueForNode(arguments, map, availability.node()); >+ >+ // This means that the value is dead. It could be dead in bytecode or it could have >+ // been killed by our DCE, which can sometimes kill things even if they were live in >+ // bytecode. >+ return ExitValue::dead(); >+ >+ case FlushedJSValue: >+ case FlushedCell: >+ case FlushedBoolean: >+ return ExitValue::inJSStack(flush.virtualRegister()); >+ >+ case FlushedInt32: >+ return ExitValue::inJSStackAsInt32(flush.virtualRegister()); >+ >+ case FlushedInt52: >+ return ExitValue::inJSStackAsInt52(flush.virtualRegister()); >+ >+ case FlushedDouble: >+ return ExitValue::inJSStackAsDouble(flush.virtualRegister()); >+ >+ case FlushedArguments: >+ return ExitValue::argumentsObjectThatWasNotCreated(); >+ } >+ >+ DFG_CRASH(m_graph, m_node, "Invalid flush format"); >+ } >+ >+ ExitValue exitValueForNode( >+ ExitArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map, >+ Node* node) > { > ASSERT(node->shouldGenerate()); > ASSERT(node->hasResult()); > > if (node) { > switch (node->op()) { >+ case BottomValue: >+ // This might arise in object materializations. I actually doubt that it would, >+ // but it seems worthwhile to be conservative. >+ return ExitValue::dead(); >+ > case JSConstant: > case Int52Constant: > case DoubleConstant: >@@ -6474,6 +6652,9 @@ private: > case PhantomArguments: > return ExitValue::argumentsObjectThatWasNotCreated(); > >+ case PhantomNewObject: >+ return ExitValue::materializeNewObject(map.get(node)); >+ > default: > break; > } >@@ -6721,7 +6902,7 @@ private: > m_out.unreachable(); > } > >- Operands<Availability>& availability() { return m_availabilityCalculator.m_availability; } >+ AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; } > > VM& vm() { return m_graph.m_vm; } > CodeBlock* codeBlock() { return m_graph.m_codeBlock; } >Index: Source/JavaScriptCore/ftl/FTLOSRExit.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExit.h (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLOSRExit.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013 Apple Inc. All rights reserved. >+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -33,6 +33,7 @@ > #include "DFGOSRExitBase.h" > #include "FTLAbbreviations.h" > #include "FTLExitArgumentList.h" >+#include "FTLExitTimeObjectMaterialization.h" > #include "FTLExitValue.h" > #include "FTLFormattedValue.h" > #include "MethodOfGettingAValueProfile.h" >@@ -160,6 +161,7 @@ struct OSRExit : public DFG::OSRExitBase > unsigned m_patchableCodeOffset; > > Operands<ExitValue> m_values; >+ Bag<ExitTimeObjectMaterialization> m_materializations; > > uint32_t m_stackmapID; > >Index: Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (working copy) >@@ -33,6 +33,7 @@ > #include "FTLExitArgumentForOperand.h" > #include "FTLJITCode.h" > #include "FTLOSRExit.h" >+#include "FTLOperations.h" > #include "FTLState.h" > #include "FTLSaveRestore.h" > #include "LinkBuffer.h" >@@ -46,6 +47,89 @@ namespace JSC { namespace FTL { > > using namespace DFG; > >+static void compileRecovery( >+ CCallHelpers& jit, const ExitValue& value, StackMaps::Record* record, StackMaps& stackmaps, >+ char *registerScratch, >+ const HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*>& materializationToPointer) >+{ >+ switch (value.kind()) { >+ case ExitValueDead: >+ jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0); >+ break; >+ >+ case ExitValueConstant: >+ jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0); >+ break; >+ >+ case ExitValueArgument: >+ record->locations[value.exitArgument().argument()].restoreInto( >+ jit, stackmaps, registerScratch, GPRInfo::regT0); >+ break; >+ >+ case ExitValueInJSStack: >+ case ExitValueInJSStackAsInt32: >+ case ExitValueInJSStackAsInt52: >+ case ExitValueInJSStackAsDouble: >+ jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0); >+ break; >+ >+ case ExitValueArgumentsObjectThatWasNotCreated: >+ // We can't actually recover this yet, but we can make the stack look sane. This is >+ // a prerequisite to running the actual arguments recovery. >+ jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0); >+ break; >+ >+ case ExitValueRecovery: >+ record->locations[value.rightRecoveryArgument()].restoreInto( >+ jit, stackmaps, registerScratch, GPRInfo::regT1); >+ record->locations[value.leftRecoveryArgument()].restoreInto( >+ jit, stackmaps, registerScratch, GPRInfo::regT0); >+ switch (value.recoveryOpcode()) { >+ case AddRecovery: >+ switch (value.recoveryFormat()) { >+ case ValueFormatInt32: >+ jit.add32(GPRInfo::regT1, GPRInfo::regT0); >+ break; >+ case ValueFormatInt52: >+ jit.add64(GPRInfo::regT1, GPRInfo::regT0); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ break; >+ case SubRecovery: >+ switch (value.recoveryFormat()) { >+ case ValueFormatInt32: >+ jit.sub32(GPRInfo::regT1, GPRInfo::regT0); >+ break; >+ case ValueFormatInt52: >+ jit.sub64(GPRInfo::regT1, GPRInfo::regT0); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ break; >+ >+ case ExitValueMaterializeNewObject: >+ jit.loadPtr(materializationToPointer.get(value.objectMaterialization()), GPRInfo::regT0); >+ break; >+ >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ >+ reboxAccordingToFormat( >+ value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2); >+} >+ > static void compileStub( > unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock) > { >@@ -64,13 +148,39 @@ static void compileStub( > > CCallHelpers jit(vm, codeBlock); > >- // We need scratch space to save all registers and to build up the JSStack. >- // Use a scratch buffer to transfer all values. >- ScratchBuffer* scratchBuffer = vm->scratchBufferForSize(sizeof(EncodedJSValue) * exit.m_values.size() + requiredScratchMemorySizeInBytes() + jitCode->unwindInfo.m_registers.size() * sizeof(uint64_t)); >+ // We need scratch space to save all registers, to build up the JS stack, to deal with unwind >+ // fixup, pointers to all of the objects we materialize, and the elements inside those objects >+ // that we materialize. >+ >+ // Figure out how much space we need for those object allocations. >+ unsigned numMaterializations = 0; >+ size_t maxMaterializationNumArguments = 0; >+ for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) { >+ numMaterializations++; >+ >+ maxMaterializationNumArguments = std::max( >+ maxMaterializationNumArguments, >+ materialization->properties().size()); >+ } >+ >+ ScratchBuffer* scratchBuffer = vm->scratchBufferForSize( >+ sizeof(EncodedJSValue) * ( >+ exit.m_values.size() + numMaterializations + maxMaterializationNumArguments) + >+ requiredScratchMemorySizeInBytes() + >+ jitCode->unwindInfo.m_registers.size() * sizeof(uint64_t)); > EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0; >- char* registerScratch = bitwise_cast<char*>(scratch + exit.m_values.size()); >+ EncodedJSValue* materializationPointers = scratch + exit.m_values.size(); >+ EncodedJSValue* materializationArguments = materializationPointers + numMaterializations; >+ char* registerScratch = bitwise_cast<char*>(materializationArguments + maxMaterializationNumArguments); > uint64_t* unwindScratch = bitwise_cast<uint64_t*>(registerScratch + requiredScratchMemorySizeInBytes()); > >+ HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*> materializationToPointer; >+ unsigned materializationCount = 0; >+ for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) { >+ materializationToPointer.add( >+ materialization, materializationPointers + materializationCount++); >+ } >+ > // Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave(). > // We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use > // that slot for saveAllRegisters(). >@@ -120,86 +230,69 @@ static void compileStub( > if (!!exit.m_valueProfile) > jit.store64(GPRInfo::regT0, exit.m_valueProfile.getSpecFailBucket(0)); > } >- >- // Save all state from wherever the exit data tells us it was, into the appropriate place in >- // the scratch buffer. This also does the reboxing. > >- for (unsigned index = exit.m_values.size(); index--;) { >- ExitValue value = exit.m_values[index]; >+ // Materialize all objects. Don't materialize an object until all of the objects it needs >+ // have been materialized. >+ HashSet<ExitTimeObjectMaterialization*> toMaterialize; >+ for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) >+ toMaterialize.add(materialization); >+ >+ while (!toMaterialize.isEmpty()) { >+ int previousToMaterializeSize = toMaterialize.size(); > >- switch (value.kind()) { >- case ExitValueDead: >- jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0); >- break; >- >- case ExitValueConstant: >- jit.move(MacroAssembler::TrustedImm64(JSValue::encode(value.constant())), GPRInfo::regT0); >- break; >- >- case ExitValueArgument: >- record->locations[value.exitArgument().argument()].restoreInto( >- jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0); >- break; >- >- case ExitValueInJSStack: >- case ExitValueInJSStackAsInt32: >- case ExitValueInJSStackAsInt52: >- case ExitValueInJSStackAsDouble: >- jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0); >- break; >- >- case ExitValueArgumentsObjectThatWasNotCreated: >- // We can't actually recover this yet, but we can make the stack look sane. This is >- // a prerequisite to running the actual arguments recovery. >- jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0); >- break; >- >- case ExitValueRecovery: >- record->locations[value.rightRecoveryArgument()].restoreInto( >- jit, jitCode->stackmaps, registerScratch, GPRInfo::regT1); >- record->locations[value.leftRecoveryArgument()].restoreInto( >- jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0); >- switch (value.recoveryOpcode()) { >- case AddRecovery: >- switch (value.recoveryFormat()) { >- case ValueFormatInt32: >- jit.add32(GPRInfo::regT1, GPRInfo::regT0); >- break; >- case ValueFormatInt52: >- jit.add64(GPRInfo::regT1, GPRInfo::regT0); >- break; >- default: >- RELEASE_ASSERT_NOT_REACHED(); >- break; >- } >- break; >- case SubRecovery: >- switch (value.recoveryFormat()) { >- case ValueFormatInt32: >- jit.sub32(GPRInfo::regT1, GPRInfo::regT0); >- break; >- case ValueFormatInt52: >- jit.sub64(GPRInfo::regT1, GPRInfo::regT0); >- break; >- default: >- RELEASE_ASSERT_NOT_REACHED(); >+ Vector<ExitTimeObjectMaterialization*> worklist; >+ worklist.appendRange(toMaterialize.begin(), toMaterialize.end()); >+ for (ExitTimeObjectMaterialization* materialization : worklist) { >+ // Check if we can do anything about this right now. >+ bool allGood = true; >+ for (ExitPropertyValue value : materialization->properties()) { >+ if (!value.value().isObjectMaterialization()) >+ continue; >+ if (toMaterialize.contains(value.value().objectMaterialization())) { >+ // Gotta skip this one, since one of its fields points to a materialization >+ // that hasn't been materialized. >+ allGood = false; > break; > } >- break; >- default: >- RELEASE_ASSERT_NOT_REACHED(); >- break; > } >- break; >+ if (!allGood) >+ continue; > >- default: >- RELEASE_ASSERT_NOT_REACHED(); >- break; >+ // All systems go for materializing the object. First we recover the values of all of >+ // its fields and then we call a function to actually allocate the beast. >+ for (unsigned propertyIndex = materialization->properties().size(); propertyIndex--;) { >+ const ExitValue& value = materialization->properties()[propertyIndex].value(); >+ compileRecovery( >+ jit, value, record, jitCode->stackmaps, registerScratch, >+ materializationToPointer); >+ jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex); >+ } >+ >+ // This call assumes that we don't pass arguments on the stack. >+ jit.setupArgumentsWithExecState( >+ CCallHelpers::TrustedImmPtr(materialization), >+ CCallHelpers::TrustedImmPtr(materializationArguments)); >+ jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(operationMaterializeObjectInOSR)), GPRInfo::nonArgGPR0); >+ jit.call(GPRInfo::nonArgGPR0); >+ jit.storePtr(GPRInfo::returnValueGPR, materializationToPointer.get(materialization)); >+ >+ // Let everyone know that we're done. >+ toMaterialize.remove(materialization); > } > >- reboxAccordingToFormat( >- value.valueFormat(), jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2); >- >+ // We expect progress! This ensures that we crash rather than looping infinitely if there >+ // is something broken about this fixpoint. Or, this could happen if we ever violate the >+ // "materializations form a DAG" rule. >+ RELEASE_ASSERT(toMaterialize.size() < previousToMaterializeSize); >+ } >+ >+ // Save all state from wherever the exit data tells us it was, into the appropriate place in >+ // the scratch buffer. This also does the reboxing. >+ >+ for (unsigned index = exit.m_values.size(); index--;) { >+ compileRecovery( >+ jit, exit.m_values[index], record, jitCode->stackmaps, registerScratch, >+ materializationToPointer); > jit.store64(GPRInfo::regT0, scratch + index); > } > >Index: Source/JavaScriptCore/ftl/FTLOperations.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOperations.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOperations.cpp (working copy) >@@ -0,0 +1,96 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 "FTLOperations.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+using namespace JSC::DFG; >+ >+extern "C" JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure) >+{ >+ VM& vm = exec->vm(); >+ NativeCallFrameTracer tracer(&vm, exec); >+ >+ Butterfly* butterfly = Butterfly::create( >+ vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0); >+ >+ return JSFinalObject::create(exec, structure, butterfly); >+} >+ >+extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR( >+ ExecState* exec, ExitTimeObjectMaterialization* materialization, EncodedJSValue* values) >+{ >+ VM& vm = exec->vm(); >+ CodeBlock* codeBlock = exec->codeBlock(); >+ >+ // We cannot GC. We've got pointers in evil places. >+ DeferGCForAWhile deferGC(vm.heap); >+ >+ // In the future, we may have many different kinds of materializations. For now we just >+ // materialize NewObject. >+ RELEASE_ASSERT(materialization->type() == PhantomNewObject); >+ >+ // First figure out what the structure is. >+ Structure* structure = nullptr; >+ for (unsigned i = materialization->properties().size(); i--;) { >+ const ExitPropertyValue& property = materialization->properties()[i]; >+ if (property.location() != PromotedLocationDescriptor(StructurePLoc)) >+ continue; >+ >+ structure = jsCast<Structure*>(JSValue::decode(values[i])); >+ } >+ RELEASE_ASSERT(structure); >+ >+ // Let's create that object! >+ JSFinalObject* result = JSFinalObject::create(vm, structure); >+ >+ // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently() >+ // because that happens to be lower-level and more convenient. It doesn't change the >+ // materialization of the property table. We want to have minimal visible effects on the >+ // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR >+ // exit. >+ for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) { >+ for (unsigned i = materialization->properties().size(); i--;) { >+ const ExitPropertyValue& property = materialization->properties()[i]; >+ if (property.location().kind() != NamedPropertyPLoc) >+ continue; >+ if (codeBlock->identifier(property.location().info()).impl() != entry.key) >+ continue; >+ >+ result->putDirect(vm, entry.offset, JSValue::decode(values[i])); >+ } >+ } >+ >+ return result; >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLOperations.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOperations.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOperations.h (working copy) >@@ -0,0 +1,50 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * 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 FTLOperations_h >+#define FTLOperations_h >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGOperations.h" >+#include "FTLExitTimeObjectMaterialization.h" >+ >+namespace JSC { namespace FTL { >+ >+extern "C" { >+ >+JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure* structure) WTF_INTERNAL; >+ >+JSCell* JIT_OPERATION operationMaterializeObjectInOSR( >+ ExecState*, ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL; >+ >+} // extern "C" >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLOperations_h >+ >Index: Source/JavaScriptCore/ftl/FTLSwitchCase.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLSwitchCase.h (revision 173837) >+++ Source/JavaScriptCore/ftl/FTLSwitchCase.h (working copy) >@@ -35,6 +35,12 @@ namespace JSC { namespace FTL { > > class SwitchCase { > public: >+ SwitchCase() >+ : m_value(nullptr) >+ , m_target(nullptr) >+ { >+ } >+ > SwitchCase(LValue value, LBasicBlock target, Weight weight) > : m_value(value) > , m_target(target) >Index: Source/JavaScriptCore/runtime/JSObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSObject.h (revision 173837) >+++ Source/JavaScriptCore/runtime/JSObject.h (working copy) >@@ -1052,7 +1052,7 @@ public: > return (maxSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>); > } > >- static JSFinalObject* create(ExecState*, Structure*); >+ static JSFinalObject* create(ExecState*, Structure*, Butterfly* = nullptr); > static JSFinalObject* create(VM&, Structure*); > static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, unsigned inlineCapacity) > { >@@ -1076,15 +1076,16 @@ protected: > private: > friend class LLIntOffsetsExtractor; > >- explicit JSFinalObject(VM& vm, Structure* structure) >- : JSObject(vm, structure) >+ explicit JSFinalObject(VM& vm, Structure* structure, Butterfly* butterfly = nullptr) >+ : JSObject(vm, structure, butterfly) > { > } > > static const unsigned StructureFlags = JSObject::StructureFlags; > }; > >-inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure) >+inline JSFinalObject* JSFinalObject::create( >+ ExecState* exec, Structure* structure, Butterfly* butterfly) > { > JSFinalObject* finalObject = new ( > NotNull, >@@ -1092,7 +1093,7 @@ inline JSFinalObject* JSFinalObject::cre > *exec->heap(), > allocationSize(structure->inlineCapacity()) > ) >- ) JSFinalObject(exec->vm(), structure); >+ ) JSFinalObject(exec->vm(), structure, butterfly); > finalObject->finishCreation(exec->vm()); > return finalObject; > } >Index: Source/JavaScriptCore/runtime/Structure.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/Structure.cpp (revision 173837) >+++ Source/JavaScriptCore/runtime/Structure.cpp (working copy) >@@ -1105,6 +1105,13 @@ PassRefPtr<StructureShape> Structure::to > return baseShape.release(); > } > >+bool Structure::canUseForAllocationsOf(Structure* other) >+{ >+ return inlineCapacity() == other->inlineCapacity() >+ && storedPrototype() == other->storedPrototype() >+ && objectInitializationBlob() == other->objectInitializationBlob(); >+} >+ > void Structure::dump(PrintStream& out) const > { > out.print(RawPointer(this), ":[", classInfo()->className, ", {"); >Index: Source/JavaScriptCore/runtime/Structure.h >=================================================================== >--- Source/JavaScriptCore/runtime/Structure.h (revision 173837) >+++ Source/JavaScriptCore/runtime/Structure.h (working copy) >@@ -433,6 +433,10 @@ public: > > PassRefPtr<StructureShape> toStructureShape(JSValue); > >+ // Determines if the two structures match enough that this one could be used for allocations >+ // of the other one. >+ bool canUseForAllocationsOf(Structure*); >+ > void dump(PrintStream&) const; > void dumpInContext(PrintStream&, DumpContext*) const; > void dumpBrief(PrintStream&, const CString&) const; >Index: Source/WTF/ChangeLog >=================================================================== >--- Source/WTF/ChangeLog (revision 173846) >+++ Source/WTF/ChangeLog (working copy) >@@ -1,3 +1,17 @@ >+2014-09-22 Filip Pizlo <fpizlo@apple.com> >+ >+ FTL should sink object allocations >+ https://bugs.webkit.org/show_bug.cgi?id=136330 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Make it possible to reset a Bag. >+ >+ * wtf/Bag.h: >+ (WTF::Bag::Bag): >+ (WTF::Bag::~Bag): >+ (WTF::Bag::clear): >+ > 2014-09-22 Sam Weinig <sam@webkit.org> > > Eliminate redundant PtrHash specializations >Index: Source/WTF/wtf/Bag.h >=================================================================== >--- Source/WTF/wtf/Bag.h (revision 173837) >+++ Source/WTF/wtf/Bag.h (working copy) >@@ -46,17 +46,23 @@ private: > > public: > Bag() >- : m_head(0) >+ : m_head(nullptr) > { > } > > ~Bag() > { >+ clear(); >+ } >+ >+ void clear() >+ { > while (m_head) { > Node* current = m_head; > m_head = current->m_next; > delete current; > } >+ m_head = nullptr; > } > > template<typename... Args>
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 136330
:
238103
|
238151
|
238154
|
238219
|
238232
|
238317
|
238320
|
238334
|
238343
|
238415
|
238419
|
238425
|
238432
|
238441
|
238487
|
238493
|
238496
|
238508
|
238514
|
238516
|
238577
|
238607
|
238629
|
238668
|
238684
|
238688
|
238689
|
238692