#ifndef DFGNaturalLoops_h
#define DFGNaturalLoops_h
#if ENABLE(DFG_JIT)
#include "DFGAnalysis.h"
#include "DFGBasicBlock.h"
#include "DFGCommon.h"
namespace JSC { namespace DFG {
class NaturalLoops;
class NaturalLoop {
public:
NaturalLoop()
: m_header(0)
, m_outerLoopIndex(UINT_MAX)
{
}
NaturalLoop(BasicBlock* header, unsigned index)
: m_header(header)
, m_outerLoopIndex(UINT_MAX)
, m_index(index)
{
}
BasicBlock* header() const { return m_header; }
unsigned size() const { return m_body.size(); }
BasicBlock* at(unsigned i) const { return m_body[i]; }
BasicBlock* operator[](unsigned i) const { return at(i); }
bool contains(BasicBlock* block) const
{
for (unsigned i = m_body.size(); i--;) {
if (m_body[i] == block)
return true;
}
ASSERT(block != header()); return false;
}
unsigned index() const { return m_index; }
bool isOuterMostLoop() const { return m_outerLoopIndex == UINT_MAX; }
void dump(PrintStream&) const;
private:
friend class NaturalLoops;
void addBlock(BasicBlock* block) { m_body.append(block); }
BasicBlock* m_header;
Vector<BasicBlock*, 4> m_body;
unsigned m_outerLoopIndex;
unsigned m_index;
};
class NaturalLoops : public Analysis<NaturalLoops> {
public:
NaturalLoops();
~NaturalLoops();
void compute(Graph&);
unsigned numLoops() const
{
ASSERT(isValid());
return m_loops.size();
}
const NaturalLoop& loop(unsigned i) const
{
ASSERT(isValid());
return m_loops[i];
}
const NaturalLoop* headerOf(BasicBlock* block) const
{
ASSERT(isValid());
const NaturalLoop* loop = innerMostLoopOf(block);
if (!loop)
return 0;
if (loop->header() == block)
return loop;
if (!ASSERT_DISABLED) {
for (; loop; loop = innerMostOuterLoop(*loop))
ASSERT(loop->header() != block);
}
return 0;
}
const NaturalLoop* innerMostLoopOf(BasicBlock* block) const
{
ASSERT(isValid());
unsigned index = block->innerMostLoopIndices[0];
if (index == UINT_MAX)
return 0;
return &m_loops[index];
}
const NaturalLoop* innerMostOuterLoop(const NaturalLoop& loop) const
{
ASSERT(isValid());
if (loop.m_outerLoopIndex == UINT_MAX)
return 0;
return &m_loops[loop.m_outerLoopIndex];
}
bool belongsTo(BasicBlock* block, const NaturalLoop& candidateLoop) const
{
ASSERT(isValid());
if (candidateLoop.size() < 4)
return candidateLoop.contains(block);
for (const NaturalLoop* loop = innerMostLoopOf(block); loop; loop = innerMostOuterLoop(*loop)) {
if (loop == &candidateLoop)
return true;
}
return false;
}
unsigned loopDepth(BasicBlock* block) const
{
unsigned depth = 0;
for (const NaturalLoop* loop = innerMostLoopOf(block); loop; loop = innerMostOuterLoop(*loop))
depth++;
return depth;
}
Vector<const NaturalLoop*> loopsOf(BasicBlock*) const;
void dump(PrintStream&) const;
private:
Vector<NaturalLoop, 4> m_loops;
};
} }
#endif // ENABLE(DFG_JIT)
#endif // DFGNaturalLoops_h