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);
......
/*
* 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)
// If the other heap has a super heap, we make sure it's present but don't
// modify its value - so we had it directly already then this doesn't change.
if (this == &other)
return;
HashMap<AbstractHeap, bool>::const_iterator iter = other.m_clobbers.begin();
HashMap<AbstractHeap, bool>::const_iterator end = other.m_clobbers.end();
for (; iter != end; ++iter)
......
......@@ -28,9 +28,11 @@
#if ENABLE(DFG_JIT)
#include "Operations.h"
namespace JSC { namespace DFG {
bool didWrites(Graph& graph, Node* node)
bool doesWrites(Graph& graph, Node* node)
{
NoOpClobberize addRead;
CheckClobberize addWrite;
......
......@@ -624,7 +624,7 @@ private:
bool m_result;
};
bool didWrites(Graph&, Node*);
bool doesWrites(Graph&, Node*);
} } // namespace JSC::DFG
......
......@@ -40,6 +40,7 @@ class DCEPhase : public Phase {
public:
DCEPhase(Graph& graph)
: Phase(graph, "dead code elimination")
, m_insertionSet(graph)
{
}
......@@ -104,75 +105,16 @@ public:
}
}
for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
BasicBlock* block = m_graph.block(blockIndex);
if (!block)
continue;
InsertionSet insertionSet(m_graph);
for (unsigned indexInBlock = block->size(); indexInBlock--;) {
Node* node = block->at(indexInBlock);
if (node->shouldGenerate())
continue;
switch (node->op()) {
case SetLocal:
case MovHint: {
ASSERT((node->op() == SetLocal) == (m_graph.m_form == ThreadedCPS));
if (node->child1().willNotHaveCheck()) {
// Consider the possibility that UInt32ToNumber is dead but its
// child isn't; if so then we should MovHint the child.
if (!node->child1()->shouldGenerate()
&& node->child1()->op() == UInt32ToNumber)
node->child1() = node->child1()->child1();
if (!node->child1()->shouldGenerate()) {
node->setOpAndDefaultFlags(ZombieHint);
node->child1() = Edge();
break;
}
node->setOpAndDefaultFlags(MovHint);
break;
}
node->setOpAndDefaultFlags(MovHintAndCheck);
node->setRefCount(1);
break;
}
case GetLocal:
case SetArgument: {
if (m_graph.m_form == ThreadedCPS) {
// Leave them as not shouldGenerate.
break;
}
}
default: {
if (node->flags() & NodeHasVarArgs) {
for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
Edge edge = m_graph.m_varArgChildren[childIdx];
if (!edge || edge.willNotHaveCheck())
continue;
insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node->codeOrigin, edge);
}
node->convertToPhantomUnchecked();
node->children.reset();
node->setRefCount(1);
break;
}
node->convertToPhantom();
eliminateIrrelevantPhantomChildren(node);
node->setRefCount(1);
break;
} }
}
insertionSet.execute(block);
if (m_graph.m_form == SSA) {
// Need to process the graph in reverse DFS order, so that we get to the uses
// of a node before we get to the node itself.
Vector<BasicBlock*> depthFirst;
m_graph.getBlocksInDepthFirstOrder(depthFirst);
for (unsigned i = depthFirst.size(); i--;)
fixupBlock(depthFirst[i]);
} else {
for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
fixupBlock(m_graph.block(blockIndex));
}
m_graph.m_refCountState = ExactRefCount;
......@@ -206,6 +148,75 @@ private:
countNode(edge.node());
}
void fixupBlock(BasicBlock* block)
{
if (!block)
return;
for (unsigned indexInBlock = block->size(); indexInBlock--;) {
Node* node = block->at(indexInBlock);
if (node->shouldGenerate())
continue;
switch (node->op()) {
case SetLocal:
case MovHint: {
ASSERT((node->op() == SetLocal) == (m_graph.m_form == ThreadedCPS));
if (node->child1().willNotHaveCheck()) {
// Consider the possibility that UInt32ToNumber is dead but its
// child isn't; if so then we should MovHint the child.
if (!node->child1()->shouldGenerate()
&& node->child1()->op() == UInt32ToNumber)
node->child1() = node->child1()->child1();
if (!node->child1()->shouldGenerate()) {
node->setOpAndDefaultFlags(ZombieHint);
node->child1() = Edge();
break;
}
node->setOpAndDefaultFlags(MovHint);
break;
}
node->setOpAndDefaultFlags(MovHintAndCheck);
node->setRefCount(1);
break;
}
case GetLocal:
case SetArgument: {
if (m_graph.m_form == ThreadedCPS) {
// Leave them as not shouldGenerate.
break;
}
}
default: {
if (node->flags() & NodeHasVarArgs) {
for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
Edge edge = m_graph.m_varArgChildren[childIdx];
if (!edge || edge.willNotHaveCheck())
continue;
m_insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node->codeOrigin, edge);
}
node->convertToPhantomUnchecked();
node->children.reset();
node->setRefCount(1);
break;
}
node->convertToPhantom();
eliminateIrrelevantPhantomChildren(node);
node->setRefCount(1);
break;
} }
}
m_insertionSet.execute(block);
}
void eliminateIrrelevantPhantomChildren(Node* node)
{
for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
......@@ -218,6 +229,7 @@ private:
}
Vector<Node*, 128> m_worklist;
InsertionSet m_insertionSet;
};
bool performDCE(Graph& graph)
......
/*
* 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 DFGEdgeDominates_h
#define DFGEdgeDominates_h
#include <wtf/Platform.h>
#if ENABLE(DFG_JIT)
#include "DFGGraph.h"
namespace JSC { namespace DFG {
class EdgeDominates {
static const bool verbose = false;
public:
EdgeDominates(Graph& graph, BasicBlock* block)
: m_graph(graph)
, m_block(block)
, m_result(true)
{
}
void operator()(Node*, Edge edge)
{
bool result = m_graph.m_dominators.dominates(edge.node()->misc.owner, m_block);
if (verbose) {
dataLog(
"Checking if ", edge, " in ", *edge.node()->misc.owner,
" dominates ", *m_block, ": ", result, "\n");
}
m_result &= result;
}
bool result() const { return m_result; }
private:
Graph& m_graph;