Commit e17632e6 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: DFG should do a high-level LICM before going to FTL

https://bugs.webkit.org/show_bug.cgi?id=118749

Reviewed by Oliver Hunt.

Implements LICM hoisting for nodes that never write anything and never read
things that are clobbered by the loop. There are some other preconditions for
hoisting, see DFGLICMPhase.cpp.

Also did a few fixes:

- ClobberSet::add was failing to switch Super entries to Direct entries in
  some cases.

- DFGClobberize.cpp needed to #include "Operations.h".

- DCEPhase needs to process the graph in reverse DFS order, when we're in SSA.

- AbstractInterpreter can now execute a Node without knowing its indexInBlock.
  Knowing the indexInBlock is an optional optimization that all other clients
  of AI still opt into, but LICM doesn't.

This makes the FTL a 2.19x speed-up on imaging-gaussian-blur.

* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreter.h:
(AbstractInterpreter):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
(JSC::DFG::::execute):
(DFG):
(JSC::DFG::::clobberWorld):
(JSC::DFG::::clobberStructures):
* dfg/DFGAtTailAbstractState.cpp: Added.
(DFG):
(JSC::DFG::AtTailAbstractState::AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::~AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::createValueForNode):
(JSC::DFG::AtTailAbstractState::forNode):
* dfg/DFGAtTailAbstractState.h: Added.
(DFG):
(AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::initializeTo):
(JSC::DFG::AtTailAbstractState::forNode):
(JSC::DFG::AtTailAbstractState::variables):
(JSC::DFG::AtTailAbstractState::block):
(JSC::DFG::AtTailAbstractState::isValid):
(JSC::DFG::AtTailAbstractState::setDidClobber):
(JSC::DFG::AtTailAbstractState::setIsValid):
(JSC::DFG::AtTailAbstractState::setBranchDirection):
(JSC::DFG::AtTailAbstractState::setFoundConstants):
(JSC::DFG::AtTailAbstractState::haveStructures):
(JSC::DFG::AtTailAbstractState::setHaveStructures):
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::insertBeforeLast):
* dfg/DFGBasicBlockInlines.h:
(DFG):
* dfg/DFGClobberSet.cpp:
(JSC::DFG::ClobberSet::add):
(JSC::DFG::ClobberSet::addAll):
* dfg/DFGClobberize.cpp:
(JSC::DFG::doesWrites):
* dfg/DFGClobberize.h:
(DFG):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::DCEPhase):
(JSC::DFG::DCEPhase::run):
(JSC::DFG::DCEPhase::fixupBlock):
(DCEPhase):
* dfg/DFGEdgeDominates.h: Added.
(DFG):
(EdgeDominates):
(JSC::DFG::EdgeDominates::EdgeDominates):
(JSC::DFG::EdgeDominates::operator()):
(JSC::DFG::EdgeDominates::result):
(JSC::DFG::edgesDominate):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::checkArray):
* dfg/DFGLICMPhase.cpp: Added.
(LICMPhase):
(JSC::DFG::LICMPhase::LICMPhase):
(JSC::DFG::LICMPhase::run):
(JSC::DFG::LICMPhase::attemptHoist):
(DFG):
(JSC::DFG::performLICM):
* dfg/DFGLICMPhase.h: Added.
(DFG):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153295 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a0caeaa4
2013-07-22 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should do a high-level LICM before going to FTL
https://bugs.webkit.org/show_bug.cgi?id=118749
Reviewed by Oliver Hunt.
Implements LICM hoisting for nodes that never write anything and never read
things that are clobbered by the loop. There are some other preconditions for
hoisting, see DFGLICMPhase.cpp.
Also did a few fixes:
- ClobberSet::add was failing to switch Super entries to Direct entries in
some cases.
- DFGClobberize.cpp needed to #include "Operations.h".
- DCEPhase needs to process the graph in reverse DFS order, when we're in SSA.
- AbstractInterpreter can now execute a Node without knowing its indexInBlock.
Knowing the indexInBlock is an optional optimization that all other clients
of AI still opt into, but LICM doesn't.
This makes the FTL a 2.19x speed-up on imaging-gaussian-blur.
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreter.h:
(AbstractInterpreter):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
(JSC::DFG::::execute):
(DFG):
(JSC::DFG::::clobberWorld):
(JSC::DFG::::clobberStructures):
* dfg/DFGAtTailAbstractState.cpp: Added.
(DFG):
(JSC::DFG::AtTailAbstractState::AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::~AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::createValueForNode):
(JSC::DFG::AtTailAbstractState::forNode):
* dfg/DFGAtTailAbstractState.h: Added.
(DFG):
(AtTailAbstractState):
(JSC::DFG::AtTailAbstractState::initializeTo):
(JSC::DFG::AtTailAbstractState::forNode):
(JSC::DFG::AtTailAbstractState::variables):
(JSC::DFG::AtTailAbstractState::block):
(JSC::DFG::AtTailAbstractState::isValid):
(JSC::DFG::AtTailAbstractState::setDidClobber):
(JSC::DFG::AtTailAbstractState::setIsValid):
(JSC::DFG::AtTailAbstractState::setBranchDirection):
(JSC::DFG::AtTailAbstractState::setFoundConstants):
(JSC::DFG::AtTailAbstractState::haveStructures):
(JSC::DFG::AtTailAbstractState::setHaveStructures):
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::insertBeforeLast):
* dfg/DFGBasicBlockInlines.h:
(DFG):
* dfg/DFGClobberSet.cpp:
(JSC::DFG::ClobberSet::add):
(JSC::DFG::ClobberSet::addAll):
* dfg/DFGClobberize.cpp:
(JSC::DFG::doesWrites):
* dfg/DFGClobberize.h:
(DFG):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::DCEPhase):
(JSC::DFG::DCEPhase::run):
(JSC::DFG::DCEPhase::fixupBlock):
(DCEPhase):
* dfg/DFGEdgeDominates.h: Added.
(DFG):
(EdgeDominates):
(JSC::DFG::EdgeDominates::EdgeDominates):
(JSC::DFG::EdgeDominates::operator()):
(JSC::DFG::EdgeDominates::result):
(JSC::DFG::edgesDominate):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::checkArray):
* dfg/DFGLICMPhase.cpp: Added.
(LICMPhase):
(JSC::DFG::LICMPhase::LICMPhase):
(JSC::DFG::LICMPhase::run):
(JSC::DFG::LICMPhase::attemptHoist):
(DFG):
(JSC::DFG::performLICM):
* dfg/DFGLICMPhase.h: Added.
(DFG):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
2013-07-21 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG Nodes should be able to abstractly tell you what they read and what they write
......
......@@ -837,6 +837,11 @@
A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CF017A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp */; };
A7D89D0017A0B8CC00773AD8 /* DFGSSAConversionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D89CF117A0B8CC00773AD8 /* DFGSSAConversionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D89D0217A0B90400773AD8 /* FTLLoweredNodeValue.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D89D0117A0B90400773AD8 /* FTLLoweredNodeValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D9A28F17A0BC7400EE2618 /* DFGAtTailAbstractState.cpp */; };
A7D9A29517A0BC7400EE2618 /* DFGAtTailAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D9A29017A0BC7400EE2618 /* DFGAtTailAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D9A29117A0BC7400EE2618 /* DFGEdgeDominates.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D9A29717A0BC7400EE2618 /* DFGLICMPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D9A29217A0BC7400EE2618 /* DFGLICMPhase.cpp */; };
A7D9A29817A0BC7400EE2618 /* DFGLICMPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D9A29317A0BC7400EE2618 /* DFGLICMPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E2EA690FB460CF00601F06 /* LiteralParser.h */; };
A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */; };
......@@ -1916,6 +1921,11 @@
A7D89CF017A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSSAConversionPhase.cpp; path = dfg/DFGSSAConversionPhase.cpp; sourceTree = "<group>"; };
A7D89CF117A0B8CC00773AD8 /* DFGSSAConversionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSSAConversionPhase.h; path = dfg/DFGSSAConversionPhase.h; sourceTree = "<group>"; };
A7D89D0117A0B90400773AD8 /* FTLLoweredNodeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLoweredNodeValue.h; path = ftl/FTLLoweredNodeValue.h; sourceTree = "<group>"; };
A7D9A28F17A0BC7400EE2618 /* DFGAtTailAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAtTailAbstractState.cpp; path = dfg/DFGAtTailAbstractState.cpp; sourceTree = "<group>"; };
A7D9A29017A0BC7400EE2618 /* DFGAtTailAbstractState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAtTailAbstractState.h; path = dfg/DFGAtTailAbstractState.h; sourceTree = "<group>"; };
A7D9A29117A0BC7400EE2618 /* DFGEdgeDominates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdgeDominates.h; path = dfg/DFGEdgeDominates.h; sourceTree = "<group>"; };
A7D9A29217A0BC7400EE2618 /* DFGLICMPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLICMPhase.cpp; path = dfg/DFGLICMPhase.cpp; sourceTree = "<group>"; };
A7D9A29317A0BC7400EE2618 /* DFGLICMPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLICMPhase.h; path = dfg/DFGLICMPhase.h; sourceTree = "<group>"; };
A7DCB77912E3D90500911940 /* WriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrier.h; sourceTree = "<group>"; };
A7E2EA690FB460CF00601F06 /* LiteralParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralParser.h; sourceTree = "<group>"; };
A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralParser.cpp; sourceTree = "<group>"; };
......@@ -2187,9 +2197,9 @@
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
932F5BE10822A1C700736975 /* jsc */,
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
932F5BD90822A1C700736975 /* JavaScriptCore.framework */,
932F5BE10822A1C700736975 /* jsc */,
141211200A48793C00480255 /* minidom */,
14BD59BF0A3E8F9000BAF59C /* testapi */,
6511230514046A4C002B101D /* testRegExp */,
......@@ -3079,6 +3089,8 @@
0F63948215E48114006A597C /* DFGArrayMode.h */,
0FC0976B1468AB4A00CF2442 /* DFGAssemblyHelpers.cpp */,
0FC0976C1468AB4A00CF2442 /* DFGAssemblyHelpers.h */,
A7D9A28F17A0BC7400EE2618 /* DFGAtTailAbstractState.cpp */,
A7D9A29017A0BC7400EE2618 /* DFGAtTailAbstractState.h */,
0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */,
0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */,
A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */,
......@@ -3132,6 +3144,7 @@
0FD3C82214115D0E00FD81CB /* DFGDriver.h */,
0FB4B51B16B62772003F696B /* DFGEdge.cpp */,
0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */,
A7D9A29117A0BC7400EE2618 /* DFGEdgeDominates.h */,
A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */,
A78A976C179738B8009DF744 /* DFGFailedFinalizer.cpp */,
A78A976D179738B8009DF744 /* DFGFailedFinalizer.h */,
......@@ -3160,6 +3173,8 @@
A78A9771179738B8009DF744 /* DFGJITFinalizer.h */,
A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */,
A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */,
A7D9A29217A0BC7400EE2618 /* DFGLICMPhase.cpp */,
A7D9A29317A0BC7400EE2618 /* DFGLICMPhase.h */,
A7D89CEC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.cpp */,
A7D89CED17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h */,
0FB4B51C16B62772003F696B /* DFGLongLivedState.cpp */,
......@@ -3528,6 +3543,7 @@
0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */,
0F63948515E4811B006A597C /* DFGArrayMode.h in Headers */,
0FC0976D1468AB4E00CF2442 /* DFGAssemblyHelpers.h in Headers */,
A7D9A29517A0BC7400EE2618 /* DFGAtTailAbstractState.h in Headers */,
0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */,
0FFB921A16D02EC50055A5DB /* DFGBasicBlockInlines.h in Headers */,
......@@ -3558,6 +3574,7 @@
0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */,
0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */,
0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */,
A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */,
A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
......@@ -3576,6 +3593,7 @@
86EC9DCC1328DF82002B2AD7 /* DFGJITCompiler.h in Headers */,
A78A9779179738B8009DF744 /* DFGJITFinalizer.h in Headers */,
A73A535B1799CD5D00170C19 /* DFGLazyJSValue.h in Headers */,
A7D9A29817A0BC7400EE2618 /* DFGLICMPhase.h in Headers */,
A7D89CFC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h in Headers */,
0FF0F19B16B729FA005DF95B /* DFGLongLivedState.h in Headers */,
A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */,
......@@ -4394,6 +4412,7 @@
0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
0F63948415E48118006A597C /* DFGArrayMode.cpp in Sources */,
0FC0976E1468AB5100CF2442 /* DFGAssemblyHelpers.cpp in Sources */,
A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */,
0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */,
A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */,
A70B083217A0B79B00DAF14B /* DFGBinarySwitch.cpp in Sources */,
......@@ -4431,6 +4450,7 @@
86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */,
A78A9778179738B8009DF744 /* DFGJITFinalizer.cpp in Sources */,
A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */,
A7D9A29717A0BC7400EE2618 /* DFGLICMPhase.cpp in Sources */,
A7D89CFB17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.cpp in Sources */,
0FF0F19916B729F6005DF95B /* DFGLongLivedState.cpp in Sources */,
A767B5B517A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp in Sources */,
......
......@@ -89,6 +89,7 @@ public:
// } else
// result = true;
bool execute(unsigned indexInBlock);
bool execute(Node*);
// Indicate the start of execution of the node. It resets any state in the node,
// that is progressively built up by executeEdges() and executeEffects(). In
......@@ -114,7 +115,7 @@ public:
// Abstractly execute the effects of the given node. This changes the abstract
// state assuming that edges have already been filtered.
bool executeEffects(unsigned indexInBlock);
bool executeEffects(unsigned indexInBlock, Node*);
bool executeEffects(unsigned clobberLimit, Node*);
void dump(PrintStream& out);
......
......@@ -119,7 +119,7 @@ void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
}
template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock, Node* node)
bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
{
if (!ASSERT_DISABLED)
verifyEdges(node);
......@@ -332,7 +332,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
break;
default:
RELEASE_ASSERT(node->op() == ValueAdd);
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).setType(SpecString | SpecInt32 | SpecNumber);
break;
}
......@@ -771,7 +771,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
m_state.setIsValid(false);
break;
case Array::Generic:
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
break;
case Array::String:
......@@ -786,7 +786,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
// implies an in-bounds access). None of this feels like it's worth it,
// so we're going with TOP for now. The same thing applies to
// clobbering the world.
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
} else
forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
......@@ -796,14 +796,14 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
break;
case Array::Int32:
if (node->arrayMode().isOutOfBounds()) {
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
} else
forNode(node).setType(SpecInt32);
break;
case Array::Double:
if (node->arrayMode().isOutOfBounds()) {
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
} else if (node->arrayMode().isSaneChain())
forNode(node).setType(SpecDouble);
......@@ -814,7 +814,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
if (node->arrayMode().isOutOfBounds())
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
break;
case Array::Int8Array:
......@@ -862,24 +862,24 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
m_state.setIsValid(false);
break;
case Array::Generic:
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
case Array::Int32:
if (node->arrayMode().isOutOfBounds())
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
case Array::Double:
if (node->arrayMode().isOutOfBounds())
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
case Array::Contiguous:
case Array::ArrayStorage:
if (node->arrayMode().isOutOfBounds())
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
case Array::SlowPutArrayStorage:
if (node->arrayMode().mayStoreToHole())
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
default:
break;
......@@ -889,13 +889,13 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
case ArrayPush:
node->setCanExit(true);
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).setType(SpecNumber);
break;
case ArrayPop:
node->setCanExit(true);
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
break;
......@@ -979,7 +979,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
// ToPrimitive will currently forget string constants. But that's not a big
// deal since we don't do any optimization on those currently.
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
SpeculatedType type = source.m_type;
if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
......@@ -1007,7 +1007,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
break;
case CellUse:
case UntypedUse:
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
default:
RELEASE_ASSERT_NOT_REACHED();
......@@ -1118,7 +1118,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
case GetMyArgumentsLengthSafe:
// This potentially clobbers all structures if the arguments object had a getter
// installed on the length property.
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
// We currently make no guarantee about what this returns because it does not
// speculate that the length property is actually a length.
forNode(node).makeTop();
......@@ -1136,7 +1136,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
node->setCanExit(true);
// This potentially clobbers all structures if the property we're accessing has
// a getter. We don't speculate against this.
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
// And the result is unknown.
forNode(node).makeTop();
break;
......@@ -1225,7 +1225,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
}
}
}
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
break;
......@@ -1294,7 +1294,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
case PutStructure:
case PhantomPutStructure:
if (!forNode(node->child1()).m_currentKnownStructure.isClear()) {
clobberStructures(indexInBlock);
clobberStructures(clobberLimit);
forNode(node->child1()).set(m_graph, node->structureTransitionData().newStructure);
m_state.setHaveStructures(true);
}
......@@ -1366,7 +1366,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
ASSERT(node->arrayMode().conversion() == Array::Convert
|| node->arrayMode().conversion() == Array::RageConvert);
node->setCanExit(true);
clobberStructures(indexInBlock);
clobberStructures(clobberLimit);
filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
m_state.setHaveStructures(true);
break;
......@@ -1378,7 +1378,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
|| value.m_currentKnownStructure.isSubsetOf(set))
m_state.setFoundConstants(true);
node->setCanExit(true);
clobberStructures(indexInBlock);
clobberStructures(clobberLimit);
filter(value, set);
m_state.setHaveStructures(true);
break;
......@@ -1425,20 +1425,20 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
break;
}
if (status.isSimpleTransition()) {
clobberStructures(indexInBlock);
clobberStructures(clobberLimit);
forNode(node->child1()).set(m_graph, status.newStructure());
m_state.setHaveStructures(true);
m_state.setFoundConstants(true);
break;
}
}
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
break;
case In:
// FIXME: We can determine when the property definitely exists based on abstract
// value information.
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).setType(SpecBoolean);
break;
......@@ -1486,7 +1486,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBloc
case Call:
case Construct:
node->setCanExit(true);
clobberWorld(node->codeOrigin, indexInBlock);
clobberWorld(node->codeOrigin, clobberLimit);
forNode(node).makeTop();
break;
......@@ -1529,12 +1529,22 @@ bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
return executeEffects(indexInBlock, node);
}
template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
{
if (!startExecuting(node))
return true;
executeEdges(node);
return executeEffects(UINT_MAX, node);
}
template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::clobberWorld(
const CodeOrigin& codeOrigin, unsigned indexInBlock)
const CodeOrigin& codeOrigin, unsigned clobberLimit)
{
clobberCapturedVars(codeOrigin);
clobberStructures(indexInBlock);
clobberStructures(clobberLimit);
}
template<typename AbstractStateType>
......@@ -1561,11 +1571,16 @@ void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigi
}
template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned indexInBlock)
void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
{
if (!m_state.haveStructures())
return;
for (size_t i = indexInBlock + 1; i--;)
if (clobberLimit >= m_state.block()->size())
clobberLimit = m_state.block()->size();
else
clobberLimit++;
ASSERT(clobberLimit <= m_state.block()->size());
for (size_t i = clobberLimit; i--;)
forNode(m_state.block()->at(i)).clobberStructures();
if (m_graph.m_form == SSA) {
HashSet<Node*>::iterator iter = m_state.block()->ssa->liveAtHead.begin();
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DFGAtTailAbstractState.h"
#if ENABLE(DFG_JIT)
#include "Operations.h"
namespace JSC { namespace DFG {
AtTailAbstractState::AtTailAbstractState()
: m_block(0)
{
}
AtTailAbstractState::~AtTailAbstractState() { }
void AtTailAbstractState::createValueForNode(Node* node)
{
m_block->ssa->valuesAtTail.add(node, AbstractValue());
}
AbstractValue& AtTailAbstractState::forNode(Node* node)
{
HashMap<Node*, AbstractValue>::iterator iter = m_block->ssa->valuesAtTail.find(node);
ASSERT(iter != m_block->ssa->valuesAtTail.end());
return iter->value;
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DFGAtTailAbstractState_h
#define DFGAtTailAbstractState_h
#include <wtf/Platform.h>
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
#include "DFGBasicBlock.h"
#include "DFGGraph.h"
namespace JSC { namespace DFG {
class AtTailAbstractState {
public:
AtTailAbstractState();
~AtTailAbstractState();
void initializeTo(BasicBlock* block)
{
m_block = block;
}
void createValueForNode(Node*);
AbstractValue& forNode(Node*);
AbstractValue& forNode(Edge edge) { return forNode(edge.node()); }
Operands<AbstractValue>& variables() { return m_block->valuesAtTail; }
BasicBlock* block() const { return m_block; }
bool isValid() { return m_block->cfaDidFinish; }
void setDidClobber(bool) { }
void setIsValid(bool isValid) { m_block->cfaDidFinish = isValid; }
void setBranchDirection(BranchDirection) { }
void setFoundConstants(bool) { }
bool haveStructures() const { return true; } // It's always safe to return true.
void setHaveStructures(bool) { }
private:
BasicBlock* m_block;
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGAtTailAbstractState_h
......@@ -62,6 +62,11 @@ struct BasicBlock : RefCounted<BasicBlock> {
void grow(size_t size) { m_nodes.grow(size); }
void append(Node* node) { m_nodes.append(node); }
void insertBeforeLast(Node* node)
{
append(last());
at(size() - 2) = node;
}
size_t numNodes() const { return phis.size() + size(); }
Node* node(size_t i) const
......
......@@ -47,8 +47,7 @@ namespace JSC { namespace DFG {
templatePre typeParams templatePost inline Node* BasicBlock::appendNonTerminal(Graph& graph, SpeculatedType type valueParamsComma valueParams) \
{ \
Node* result = graph.addNode(type valueParamsComma valueArgs); \
append(last()); \
at(size() - 2) = result; \
insertBeforeLast(result); \
return result; \
}
DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE)
......
......@@ -40,7 +40,7 @@ ClobberSet::~ClobberSet() { }
void ClobberSet::add(AbstractHeap heap)
{
HashMap<AbstractHeap, bool>::AddResult result = m_clobbers.add(heap, true);
if (result.isNewEntry) {
if (!result.isNewEntry) {
if (result.iterator->value)
return;
result.iterator->value = true;
......@@ -60,6 +60,9 @@ void ClobberSet::addAll(const ClobberSet& other)