DFGStoreBarrierClusteringPhase.cpp [plain text]
#include "config.h"
#include "DFGStoreBarrierClusteringPhase.h"
#if ENABLE(DFG_JIT)
#include "DFGDoesGC.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGMayExit.h"
#include "DFGPhase.h"
#include "JSCInlines.h"
#include <wtf/FastBitVector.h>
namespace JSC { namespace DFG {
namespace {
class StoreBarrierClusteringPhase : public Phase {
public:
StoreBarrierClusteringPhase(Graph& graph)
: Phase(graph, "store barrier fencing")
, m_insertionSet(graph)
{
}
bool run()
{
size_t maxSize = 0;
for (BasicBlock* block : m_graph.blocksInNaturalOrder())
maxSize = std::max(maxSize, block->size());
m_barrierPoints.resize(maxSize);
for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
size_t blockSize = block->size();
doBlock(block);
m_barrierPoints.clearRange(0, blockSize);
}
return true;
}
private:
struct ChildAndOrigin {
ChildAndOrigin() { }
ChildAndOrigin(Node* child, CodeOrigin semanticOrigin)
: child(child)
, semanticOrigin(semanticOrigin)
{
}
Node* child { nullptr };
CodeOrigin semanticOrigin;
};
void doBlock(BasicBlock* block)
{
ASSERT(m_barrierPoints.isEmpty());
bool futureGC = true;
for (unsigned nodeIndex = block->size(); nodeIndex--;) {
Node* node = block->at(nodeIndex);
if (doesGC(m_graph, node) || mayExit(m_graph, node) != DoesNotExit) {
futureGC = true;
continue;
}
if (node->isStoreBarrier() && futureGC) {
m_barrierPoints[nodeIndex] = true;
futureGC = false;
}
}
for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
Node* node = block->at(nodeIndex);
if (!node->isStoreBarrier())
continue;
DFG_ASSERT(m_graph, node, !node->origin.wasHoisted);
DFG_ASSERT(m_graph, node, node->child1().useKind() == KnownCellUse, node->op(), node->child1().useKind());
NodeOrigin origin = node->origin;
m_neededBarriers.append(ChildAndOrigin(node->child1().node(), origin.semantic));
node->remove(m_graph);
if (!m_barrierPoints[nodeIndex])
continue;
std::sort(
m_neededBarriers.begin(), m_neededBarriers.end(),
[&] (const ChildAndOrigin& a, const ChildAndOrigin& b) -> bool {
return a.child < b.child;
});
removeRepeatedElements(
m_neededBarriers,
[&] (const ChildAndOrigin& a, const ChildAndOrigin& b) -> bool{
return a.child == b.child;
});
for (auto iter = m_neededBarriers.begin(); iter != m_neededBarriers.end(); ++iter) {
Node* child = iter->child;
CodeOrigin semanticOrigin = iter->semanticOrigin;
NodeType type;
if (Options::useConcurrentBarriers() && iter == m_neededBarriers.begin())
type = FencedStoreBarrier;
else
type = StoreBarrier;
m_insertionSet.insertNode(
nodeIndex, SpecNone, type, origin.withSemantic(semanticOrigin),
Edge(child, KnownCellUse));
}
m_neededBarriers.shrink(0);
}
m_insertionSet.execute(block);
}
InsertionSet m_insertionSet;
FastBitVector m_barrierPoints;
Vector<ChildAndOrigin> m_neededBarriers;
};
}
bool performStoreBarrierClustering(Graph& graph)
{
return runPhase<StoreBarrierClusteringPhase>(graph);
}
} }
#endif // ENABLE(DFG_JIT)