#pragma once
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
#include "DFGAvailability.h"
#include "DFGAvailabilityMap.h"
#include "DFGBranchDirection.h"
#include "DFGFlushedAt.h"
#include "DFGNode.h"
#include "DFGNodeAbstractValuePair.h"
#include "DFGNodeOrigin.h"
#include "DFGStructureClobberState.h"
#include "Operands.h"
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
class Graph;
class InsertionSet;
typedef Vector<BasicBlock*, 2> PredecessorList;
typedef Vector<Node*, 8> BlockNodeList;
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* tryAt(size_t i) const
{
if (i >= size())
return nullptr;
return at(i);
}
Node*& operator[](size_t i) { return at(i); }
Node* operator[](size_t i) const { return at(i); }
ALWAYS_INLINE NodeAndIndex findTerminal() const
{
size_t i = size();
while (i--) {
Node* node = at(i);
switch (node->op()) {
case Jump:
case Branch:
case Switch:
case Return:
case TailCall:
case DirectTailCall:
case TailCallVarargs:
case TailCallForwardVarargs:
case Unreachable:
return NodeAndIndex(node, i);
case Check: case Phantom:
case PhantomLocal:
case Flush:
break;
default:
return NodeAndIndex();
}
}
return NodeAndIndex();
}
ALWAYS_INLINE Node* terminal() const
{
return findTerminal().node;
}
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 insertBeforeTerminal(Node* node)
{
NodeAndIndex result = findTerminal();
if (!result)
append(node);
else
m_nodes.insert(result.index, node);
}
void replaceTerminal(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;
BlockNodeList::iterator begin() { return m_nodes.begin(); }
BlockNodeList::iterator end() { return m_nodes.end(); }
unsigned numSuccessors() { return terminal()->numSuccessors(); }
BasicBlock*& successor(unsigned index)
{
return terminal()->successor(index);
}
BasicBlock*& successorForCondition(bool condition)
{
return terminal()->successorForCondition(condition);
}
Node::SuccessorsIterable successors()
{
return terminal()->successors();
}
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...);
template<typename... Params>
Node* replaceTerminal(Graph&, SpeculatedType, Params...);
void dump(PrintStream& out) const;
void didLink()
{
#if !ASSERT_DISABLED
isLinked = true;
#endif
}
unsigned bytecodeBegin;
BlockIndex index;
bool isOSRTarget;
bool cfaHasVisited;
bool cfaShouldRevisit;
bool cfaFoundConstants;
bool cfaDidFinish;
StructureClobberState cfaStructureClobberStateAtHead;
StructureClobberState cfaStructureClobberStateAtTail;
BranchDirection cfaBranchDirection;
#if !ASSERT_DISABLED
bool isLinked;
#endif
bool isReachable;
Vector<Node*> phis;
PredecessorList predecessors;
Operands<Node*> variablesAtHead;
Operands<Node*> variablesAtTail;
Operands<AbstractValue> valuesAtHead;
Operands<AbstractValue> valuesAtTail;
Operands<AbstractValue> intersectionOfPastValuesAtHead;
bool intersectionOfCFAHasVisited;
float executionCount;
static const unsigned numberOfInnerMostLoopIndices = 2;
unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices];
struct SSAData {
WTF_MAKE_FAST_ALLOCATED;
public:
void invalidate()
{
liveAtTail.clear();
liveAtHead.clear();
valuesAtHead.clear();
valuesAtTail.clear();
}
AvailabilityMap availabilityAtHead;
AvailabilityMap availabilityAtTail;
Vector<NodeFlowProjection> liveAtHead;
Vector<NodeFlowProjection> liveAtTail;
Vector<NodeAbstractValuePair> valuesAtHead;
Vector<NodeAbstractValuePair> valuesAtTail;
SSAData(BasicBlock*);
~SSAData();
};
std::unique_ptr<SSAData> ssa;
private:
friend class InsertionSet;
BlockNodeList m_nodes;
};
typedef Vector<BasicBlock*, 5> BlockList;
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)