#ifndef DFGBasicBlock_h
#define DFGBasicBlock_h
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
#include "DFGAvailability.h"
#include "DFGBranchDirection.h"
#include "DFGFlushedAt.h"
#include "DFGNode.h"
#include "Operands.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
class Graph;
class InsertionSet;
typedef Vector<BasicBlock*, 2> PredecessorList;
struct BasicBlock : RefCounted<BasicBlock> {
BasicBlock(
unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals,
float executionCount);
~BasicBlock();
void ensureLocals(unsigned newNumLocals);
size_t size() const { return m_nodes.size(); }
bool isEmpty() const { return !size(); }
Node*& at(size_t i) { return m_nodes[i]; }
Node* at(size_t i) const { return m_nodes[i]; }
Node*& operator[](size_t i) { return at(i); }
Node* operator[](size_t i) const { return at(i); }
Node* last() const { return at(size() - 1); }
void resize(size_t size) { m_nodes.resize(size); }
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
{
if (i < phis.size())
return phis[i];
return at(i - phis.size());
}
bool isPhiIndex(size_t i) const { return i < phis.size(); }
bool isInPhis(Node* node) const;
bool isInBlock(Node* myNode) const;
unsigned numSuccessors() { return last()->numSuccessors(); }
BasicBlock*& successor(unsigned index)
{
return last()->successor(index);
}
BasicBlock*& successorForCondition(bool condition)
{
return last()->successorForCondition(condition);
}
void removePredecessor(BasicBlock* block);
void replacePredecessor(BasicBlock* from, BasicBlock* to);
template<typename... Params>
Node* appendNode(Graph&, SpeculatedType, Params...);
template<typename... Params>
Node* appendNonTerminal(Graph&, SpeculatedType, Params...);
void dump(PrintStream& out) const;
unsigned bytecodeBegin;
BlockIndex index;
bool isOSRTarget;
bool cfaHasVisited;
bool cfaShouldRevisit;
bool cfaFoundConstants;
bool cfaDidFinish;
BranchDirection cfaBranchDirection;
#if !ASSERT_DISABLED
bool isLinked;
#endif
bool isReachable;
Vector<Node*> phis;
PredecessorList predecessors;
Operands<Node*, NodePointerTraits> variablesAtHead;
Operands<Node*, NodePointerTraits> variablesAtTail;
Operands<AbstractValue> valuesAtHead;
Operands<AbstractValue> valuesAtTail;
float executionCount;
static const unsigned numberOfInnerMostLoopIndices = 2;
unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices];
struct SSAData {
Operands<Availability> availabilityAtHead;
Operands<Availability> availabilityAtTail;
HashSet<Node*> liveAtHead;
HashSet<Node*> liveAtTail;
HashMap<Node*, AbstractValue> valuesAtHead;
HashMap<Node*, AbstractValue> valuesAtTail;
SSAData(BasicBlock*);
~SSAData();
};
OwnPtr<SSAData> ssa;
private:
friend class InsertionSet;
Vector<Node*, 8> m_nodes;
};
struct UnlinkedBlock {
BasicBlock* m_block;
bool m_needsNormalLinking;
bool m_needsEarlyReturnLinking;
UnlinkedBlock() { }
explicit UnlinkedBlock(BasicBlock* block)
: m_block(block)
, m_needsNormalLinking(true)
, m_needsEarlyReturnLinking(false)
{
}
};
static inline unsigned getBytecodeBeginForBlock(BasicBlock** basicBlock)
{
return (*basicBlock)->bytecodeBegin;
}
static inline BasicBlock* blockForBytecodeOffset(Vector<BasicBlock*>& linkingTargets, unsigned bytecodeBegin)
{
return *binarySearch<BasicBlock*, unsigned>(linkingTargets, linkingTargets.size(), bytecodeBegin, getBytecodeBeginForBlock);
}
} }
#endif // ENABLE(DFG_JIT)
#endif // DFGBasicBlock_h