https://bugs.webkit.org/show_bug.cgi?id=144084
Reviewed by Ryosuke Niwa and Mark Lam.
This makes it easier to do epoch-based analyses on nodes. I plan to do just that in
https://bugs.webkit.org/show_bug.cgi?id=143735. Currently the epoch field is not yet
used.
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
* dfg/DFGCSEPhase.cpp:
* dfg/DFGEpoch.h:
(JSC::DFG::Epoch::fromUnsigned):
(JSC::DFG::Epoch::toUnsigned):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::clearReplacements):
(JSC::DFG::Graph::clearEpochs):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::performSubstitutionForEdge):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::replaceWith):
(JSC::DFG::Node::replacement):
(JSC::DFG::Node::setReplacement):
(JSC::DFG::Node::epoch):
(JSC::DFG::Node::setEpoch):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183162
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-04-22 Filip Pizlo <fpizlo@apple.com>
+
+ Nodes should have an optional epoch field
+ https://bugs.webkit.org/show_bug.cgi?id=144084
+
+ Reviewed by Ryosuke Niwa and Mark Lam.
+
+ This makes it easier to do epoch-based analyses on nodes. I plan to do just that in
+ https://bugs.webkit.org/show_bug.cgi?id=143735. Currently the epoch field is not yet
+ used.
+
+ * dfg/DFGCPSRethreadingPhase.cpp:
+ (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
+ * dfg/DFGCSEPhase.cpp:
+ * dfg/DFGEpoch.h:
+ (JSC::DFG::Epoch::fromUnsigned):
+ (JSC::DFG::Epoch::toUnsigned):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::clearReplacements):
+ (JSC::DFG::Graph::clearEpochs):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::performSubstitutionForEdge):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::Node):
+ (JSC::DFG::Node::replaceWith):
+ (JSC::DFG::Node::replacement):
+ (JSC::DFG::Node::setReplacement):
+ (JSC::DFG::Node::epoch):
+ (JSC::DFG::Node::setEpoch):
+ * dfg/DFGSSAConversionPhase.cpp:
+ (JSC::DFG::SSAConversionPhase::run):
+
2015-04-22 Mark Lam <mark.lam@apple.com>
Fix assertion failure and race condition in Options::dumpSourceAtDFGTime().
if (otherNode->op() == GetLocal) {
// Replace all references to this GetLocal with otherNode.
- node->replacement = otherNode;
+ node->setReplacement(otherNode);
return;
}
ASSERT(otherNode->op() == SetLocal);
- node->replacement = otherNode->child1().node();
+ node->setReplacement(otherNode->child1().node());
return;
}
if (m_node->op() == Identity) {
m_node->convertToCheck();
- m_node->replacement = m_node->child1().node();
+ m_node->setReplacement(m_node->child1().node());
m_changed = true;
} else {
// This rule only makes sense for local CSE, since in SSA form we have already
if (m_node->op() == Identity) {
m_node->convertToCheck();
- m_node->replacement = m_node->child1().node();
+ m_node->setReplacement(m_node->child1().node());
m_changed = true;
} else
clobberize(m_graph, m_node, *this);
{
}
+ static Epoch fromUnsigned(unsigned value)
+ {
+ Epoch result;
+ result.m_epoch = value;
+ return result;
+ }
+
+ unsigned toUnsigned() const
+ {
+ return m_epoch;
+ }
+
static Epoch first()
{
Epoch result;
if (!block)
continue;
for (unsigned phiIndex = block->phis.size(); phiIndex--;)
- block->phis[phiIndex]->replacement = 0;
+ block->phis[phiIndex]->setReplacement(nullptr);
for (unsigned nodeIndex = block->size(); nodeIndex--;)
- block->at(nodeIndex)->replacement = 0;
+ block->at(nodeIndex)->setReplacement(nullptr);
+ }
+}
+
+void Graph::clearEpochs()
+{
+ for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ for (unsigned phiIndex = block->phis.size(); phiIndex--;)
+ block->phis[phiIndex]->setEpoch(Epoch());
+ for (unsigned nodeIndex = block->size(); nodeIndex--;)
+ block->at(nodeIndex)->setEpoch(Epoch());
}
}
return;
// Check if there is any replacement.
- Node* replacement = child->replacement;
+ Node* replacement = child->replacement();
if (!replacement)
return;
void clearFlagsOnAllNodes(NodeFlags);
void clearReplacements();
+ void clearEpochs();
void initializeNodeOwners();
BlockList blocksInPreOrder();
#include "DFGArithMode.h"
#include "DFGArrayMode.h"
#include "DFGCommon.h"
+#include "DFGEpoch.h"
#include "DFGLazyJSValue.h"
#include "DFGNodeFlags.h"
#include "DFGNodeOrigin.h"
, m_virtualRegister(VirtualRegister())
, m_refCount(1)
, m_prediction(SpecNone)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
}
, m_prediction(SpecNone)
, m_opInfo(0)
, m_opInfo2(0)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
}
, m_prediction(SpecNone)
, m_opInfo(0)
, m_opInfo2(0)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
setResult(result);
ASSERT(!(m_flags & NodeHasVarArgs));
, m_prediction(SpecNone)
, m_opInfo(imm.m_value)
, m_opInfo2(0)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
}
, m_prediction(SpecNone)
, m_opInfo(imm.m_value)
, m_opInfo2(0)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
setResult(result);
ASSERT(!(m_flags & NodeHasVarArgs));
, m_prediction(SpecNone)
, m_opInfo(imm1.m_value)
, m_opInfo2(imm2.m_value)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
ASSERT(!(m_flags & NodeHasVarArgs));
}
, m_prediction(SpecNone)
, m_opInfo(imm1.m_value)
, m_opInfo2(imm2.m_value)
- , replacement(nullptr)
, owner(nullptr)
{
+ m_misc.replacement = nullptr;
setOpAndDefaultFlags(op);
ASSERT(m_flags & NodeHasVarArgs);
}
void replaceWith(Node* other)
{
convertToPhantom();
- replacement = other;
+ setReplacement(other);
}
void convertToIdentity();
return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
}
+ Node* replacement() const
+ {
+ return m_misc.replacement;
+ }
+
+ void setReplacement(Node* replacement)
+ {
+ m_misc.replacement = replacement;
+ }
+
+ Epoch epoch() const
+ {
+ return Epoch::fromUnsigned(m_misc.epoch);
+ }
+
+ void setEpoch(Epoch epoch)
+ {
+ m_misc.epoch = epoch.toUnsigned();
+ }
+
void dumpChildren(PrintStream& out)
{
if (!child1())
// will tell you which basic block a node belongs to. You cannot rely on this persisting
// across transformations unless you do the maintenance work yourself. Other phases use
// Node::replacement, but they do so manually: first you do Graph::clearReplacements()
- // and then you set, and use, replacement's yourself.
+ // and then you set, and use, replacement's yourself. Same thing for epoch.
//
// Bottom line: don't use these fields unless you initialize them yourself, or by
// calling some appropriate methods that initialize them the way you want. Otherwise,
// these fields are meaningless.
- Node* replacement;
+private:
+ union {
+ Node* replacement;
+ unsigned epoch;
+ } m_misc;
+public:
BasicBlock* owner;
};
}
Node* node = def->value();
- if (node->replacement) {
+ if (node->replacement()) {
// This will occur when a SetLocal had a GetLocal as its source. The
// GetLocal would get replaced with an actual SSA value by the time we get
// here. Note that the SSA value with which the GetLocal got replaced
// would not in turn have a replacement.
- node = node->replacement;
- ASSERT(!node->replacement);
+ node = node->replacement();
+ ASSERT(!node->replacement());
}
if (verbose)
dataLog("Mapping: ", VirtualRegister(valueForOperand.operandForIndex(i)), " -> ", node, "\n");
node->convertToPhantom();
if (verbose)
dataLog("Replacing node ", node, " with ", valueForOperand.operand(variable->local()), "\n");
- node->replacement = valueForOperand.operand(variable->local());
+ node->setReplacement(valueForOperand.operand(variable->local()));
break;
}