from the other nodes
https://bugs.webkit.org/show_bug.cgi?id=80361
Reviewed by Filip Pizlo.
This would make it more efficient to remove the redundant Phi nodes or
insert new Phi nodes for SSA, besides providing a cleaner BasicBlock structure.
This is performance neutral on SunSpider, V8 and Kraken.
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::clobberStructures):
(JSC::DFG::AbstractState::dump):
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::BasicBlock):
(BasicBlock):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::addToGraph):
(JSC::DFG::ByteCodeParser::insertPhiNode):
* dfg/DFGCFAPhase.cpp:
(JSC::DFG::CFAPhase::performBlockCFA):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::impureCSE):
(JSC::DFG::CSEPhase::globalVarLoadElimination):
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::checkFunctionElimination):
(JSC::DFG::CSEPhase::checkStructureLoadElimination):
(JSC::DFG::CSEPhase::getByOffsetLoadElimination):
(JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::getScopeChainLoadElimination):
(JSC::DFG::CSEPhase::performBlockCSE):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@110008
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-03-06 Yuqiang Xian <yuqiang.xian@intel.com>
+
+ DFG BasicBlock should group the Phi nodes together and separate them
+ from the other nodes
+ https://bugs.webkit.org/show_bug.cgi?id=80361
+
+ Reviewed by Filip Pizlo.
+
+ This would make it more efficient to remove the redundant Phi nodes or
+ insert new Phi nodes for SSA, besides providing a cleaner BasicBlock structure.
+ This is performance neutral on SunSpider, V8 and Kraken.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::clobberStructures):
+ (JSC::DFG::AbstractState::dump):
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::BasicBlock):
+ (BasicBlock):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::addToGraph):
+ (JSC::DFG::ByteCodeParser::insertPhiNode):
+ * dfg/DFGCFAPhase.cpp:
+ (JSC::DFG::CFAPhase::performBlockCFA):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::pureCSE):
+ (JSC::DFG::CSEPhase::impureCSE):
+ (JSC::DFG::CSEPhase::globalVarLoadElimination):
+ (JSC::DFG::CSEPhase::getByValLoadElimination):
+ (JSC::DFG::CSEPhase::checkFunctionElimination):
+ (JSC::DFG::CSEPhase::checkStructureLoadElimination):
+ (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
+ (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
+ (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
+ (JSC::DFG::CSEPhase::getScopeChainLoadElimination):
+ (JSC::DFG::CSEPhase::performBlockCSE):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
2012-03-06 Mark Hahnenberg <mhahnenberg@apple.com>
GCActivityCallback timer should vary with the length of the previous GC
PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING);
if (!m_haveStructures)
return;
- for (size_t i = indexInBlock + 1; i-- > m_block->startExcludingPhis;)
+ for (size_t i = indexInBlock + 1; i--;)
forNode(m_block->at(i)).clobberStructures();
for (size_t i = 0; i < m_variables.numberOfArguments(); ++i)
m_variables.argument(i).clobberStructures();
void AbstractState::dump(FILE* out)
{
bool first = true;
- for (size_t i = m_block->startExcludingPhis; i < m_block->size(); ++i) {
+ for (size_t i = 0; i < m_block->size(); ++i) {
NodeIndex index = m_block->at(i);
AbstractValue& value = m_nodes[index];
if (value.isClear())
, isLinked(false)
#endif
, isReachable(false)
- , startExcludingPhis(0)
, variablesAtHead(numArguments, numLocals)
, variablesAtTail(numArguments, numLocals)
, valuesAtHead(numArguments, numLocals)
bool isLinked;
#endif
bool isReachable;
- unsigned startExcludingPhis;
+ Vector<NodeIndex> phis;
PredecessorList m_predecessors;
Operands<NodeIndex, NodeIndexTraits> variablesAtHead;
{
NodeIndex resultIndex = (NodeIndex)m_graph.size();
m_graph.append(Node(op, currentCodeOrigin(), child1, child2, child3));
+ ASSERT(op != Phi);
m_currentBlock->append(resultIndex);
if (op & NodeMustGenerate)
{
NodeIndex resultIndex = (NodeIndex)m_graph.size();
m_graph.append(Node(op, currentCodeOrigin(), info, child1, child2, child3));
- m_currentBlock->append(resultIndex);
+ if (op == Phi)
+ m_currentBlock->phis.append(resultIndex);
+ else
+ m_currentBlock->append(resultIndex);
if (op & NodeMustGenerate)
m_graph.ref(resultIndex);
{
NodeIndex resultIndex = (NodeIndex)m_graph.size();
m_graph.append(Node(op, currentCodeOrigin(), info1, info2, child1, child2, child3));
+ ASSERT(op != Phi);
m_currentBlock->append(resultIndex);
if (op & NodeMustGenerate)
{
NodeIndex resultIndex = (NodeIndex)m_graph.size();
m_graph.append(Node(Node::VarArg, op, currentCodeOrigin(), info1, info2, m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs));
+ ASSERT(op != Phi);
m_currentBlock->append(resultIndex);
m_numPassedVarArgs = 0;
{
NodeIndex resultIndex = (NodeIndex)m_graph.size();
m_graph.append(Node(Phi, currentCodeOrigin(), info));
- block->prepend(resultIndex);
- ++block->startExcludingPhis;
+ block->phis.append(resultIndex);
return resultIndex;
}
dumpOperands(block->valuesAtHead, WTF::dataFile());
dataLog("\n");
#endif
- for (unsigned i = block->startExcludingPhis; i < block->size(); ++i) {
+ for (unsigned i = 0; i < block->size(); ++i) {
NodeIndex nodeIndex = block->at(i);
if (!m_graph[nodeIndex].shouldGenerate())
continue;
NodeIndex child2 = canonicalize(node.child2());
NodeIndex child3 = canonicalize(node.child3());
- for (unsigned i = endIndexForPureCSE(); i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = endIndexForPureCSE(); i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1 || index == child2 || index == child3)
break;
NodeIndex child2 = canonicalize(node.child2());
NodeIndex child3 = canonicalize(node.child3());
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1 || index == child2 || index == child3)
break;
NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
switch (node.op) {
NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1 || index == canonicalize(child2))
break;
bool checkFunctionElimination(JSFunction* function, NodeIndex child1)
{
- for (unsigned i = endIndexForPureCSE(); i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = endIndexForPureCSE(); i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1)
break;
bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1)
break;
NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1)
break;
NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1)
break;
NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, bool hasIntegerIndexPrediction)
{
- for (unsigned i = m_indexInBlock; i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1)
break;
NodeIndex getScopeChainLoadElimination(unsigned depth)
{
- for (unsigned i = endIndexForPureCSE(); i-- > m_currentBlock->startExcludingPhis;) {
+ for (unsigned i = endIndexForPureCSE(); i--;) {
NodeIndex index = m_currentBlock->at(i);
Node& node = m_graph[index];
if (node.op == GetScopeChain
for (unsigned i = 0; i < LastNodeId; ++i)
m_lastSeen[i] = UINT_MAX;
- for (m_indexInBlock = block.startExcludingPhis; m_indexInBlock < block.size(); ++m_indexInBlock) {
+ for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
m_compileIndex = block[m_indexInBlock];
performNodeCSE(m_graph[m_compileIndex]);
}
for (size_t b = 0; b < m_blocks.size(); ++b) {
BasicBlock* block = m_blocks[b].get();
dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "");
+ dataLog(" Phi Nodes:\n");
+ for (size_t i = 0; i < block->phis.size(); ++i)
+ dump(block->phis[i]);
dataLog(" vars before: ");
if (block->cfaHasVisited)
dumpOperands(block->valuesAtHead, WTF::dataFile());
verificationSucceeded.link(&m_jit);
}
- for (m_indexInBlock = block.startExcludingPhis; m_indexInBlock < block.size(); ++m_indexInBlock) {
+ for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
m_compileIndex = block[m_indexInBlock];
Node& node = at(m_compileIndex);
m_codeOriginForOSR = node.codeOrigin;