in vm/jitrino/src/optimizer/syncopt.cpp [1577:1779]
void SyncOpt::findBalancedExits_Stage3(bool optimistic, bool use_IncRecCount,
SyncOptDfValue *entrySolution,
SyncOptDfValue *exitSolution,
SyncClique *bottomClique,
SyncClique **entryCliques, SyncClique **exitCliques,
StlMap<Inst *, StlVectorSet<SyncClique *> *> &needRecCount,
StlMap<Inst *, SyncClique *> &monitorCliques)
{
// first scan all monitor instructions and make sure their Opnd matches
// match their clique's Opnd; if not, link to bottom.
{
StlMap<Inst *, SyncClique *>::iterator
miter = monitorCliques.begin(),
mend = monitorCliques.end();
for ( ; miter != mend; ++miter) {
Inst *inst = (*miter).first;
SyncClique *clique = (*miter).second;
Opnd *obj = inst->getSrc(0);
clique = clique->find();
if (clique->opnd) {
if (clique->opnd != obj) {
clique->link(bottomClique);
}
} else {
clique->opnd = obj;
}
}
bottomClique = bottomClique->find();
}
// now any monitor inst in a clique with another monitor inst with
// un-matching opnd has been linked to bottom.
StlVectorSet<SyncClique *> badMonitors(mm);
StlVectorSet<SyncClique *> dependentOnBadMonitors(mm);
StlVectorSet<Inst *> badMonitorExits(mm);
StlVector<Inst *> newBadMonitorExits(mm);
SyncClique *bottomCliqueRoot = bottomClique->find();
if (Log::isEnabled()) {
Log::out() << " beginning Stage3" << ::std::endl;
}
bool needToCheckAgain = true;
while (needToCheckAgain) {
needToCheckAgain = false;
if (Log::isEnabled()) {
Log::out() << " beginning Stage3 iteration" << ::std::endl;
}
StlMap<Inst *, SyncClique *>::iterator
miter = monitorCliques.begin(),
mend = monitorCliques.end();
for ( ; miter != mend; ++miter) {
Inst *inst = (*miter).first;
if ((inst->getOpcode() != Op_TauMonitorExit) &&
(inst->getOpcode() != Op_OptimisticBalancedMonitorExit))
continue;
SyncClique *clique = (*miter).second;
SyncClique *cliqueRoot = clique->find();
if (badMonitorExits.has(inst)) {
continue;
}
bool badclique = false;
badclique = monitorExitIsBad(inst, clique, cliqueRoot, bottomCliqueRoot);
// at this point, opnd should be set for each clique root; check whether
// monitorExit opnd matches the clique opnd, if not, add it to newBadMonitorExits.
if (badclique) {
newBadMonitorExits.push_back(inst);
// process any exception edge to merge monitors. If anything changed, we
// will have to re-process everything.
StlMap<Inst *, StlVectorSet<SyncClique *> *>::iterator
foundDeps = needRecCount.find(inst),
endDeps = needRecCount.end();
if (foundDeps != endDeps) {
StlVectorSet<SyncClique *> *deps = (*foundDeps).second;
dependentOnBadMonitors.insert(deps->begin(), deps->end());
}
}
}
if (Log::isEnabled()) {
Log::out() << " done Stage3a" << ::std::endl;
}
// union all new badMonitorExits with bottom
StlVectorSet<Inst *>::iterator
monExitIter = newBadMonitorExits.begin(),
monExitEnd = newBadMonitorExits.end();
for ( ; monExitIter != monExitEnd; ++monExitIter) {
Inst *monExit = *monExitIter;
SyncClique *clique = monitorCliques[monExit];
if (Log::isEnabled()) {
Log::out() << " linking11 badMonitor ";
clique->print(Log::out());
Log::out() << " with bottom (";
bottomClique->print(Log::out());
Log::out() << ")" << ::std::endl;
}
bottomCliqueRoot->link(clique);
}
bottomCliqueRoot = bottomCliqueRoot->find();
if (Log::isEnabled()) {
Log::out() << " done Stage3b" << ::std::endl;
}
// merge any new dependent monitors from dependentOnBadMonitors
bool foundDependentMonitor = false;
StlVectorSet<SyncClique *>::iterator
depMonIter = dependentOnBadMonitors.begin(),
depMonEnd = dependentOnBadMonitors.end();
for ( ; depMonIter != depMonEnd; ++depMonIter) {
SyncClique *depMonitor = *depMonIter;
SyncClique *depMonRoot = depMonitor->find();
if (depMonRoot != bottomCliqueRoot) {
foundDependentMonitor = true; // we need to re-iterate
if (Log::isEnabled()) {
Log::out() << " linking12 depMonRoot ";
depMonRoot->print(Log::out());
Log::out() << " with bottom (";
bottomCliqueRoot->print(Log::out());
Log::out() << ")" << ::std::endl;
}
bottomCliqueRoot->link(depMonRoot);
bottomCliqueRoot = bottomCliqueRoot->find(); // may have changed
}
}
if (Log::isEnabled()) {
Log::out() << " done Stage3c" << ::std::endl;
}
// add effect of the exception edge from each newly bad exit,
// unless optimistic (in which case we included it previously)
bool differs = foundDependentMonitor;
if (!optimistic) {
StlVectorSet<Inst *>::iterator
newBadExitIter = newBadMonitorExits.begin(),
newBadExitEnd = newBadMonitorExits.end();
for ( ; newBadExitIter != newBadExitEnd; ++newBadExitIter) {
Inst *newBadExit = *newBadExitIter;
Node *node = newBadExit->getNode();
U_32 nodeId = node->getId();
U_32 nodeDepth = exitSolution[nodeId].getDepth();
Edge *e = (Edge *)node->getExceptionEdge();
Node *target = e->getTargetNode();
U_32 targetId = target->getId();
U_32 targetDepth = entrySolution[targetId].getDepth();
SyncClique *nodeStack = exitCliques[nodeId];
SyncClique *targetStack = entryCliques[targetId];
if (!differs) {
if (targetDepth != nodeDepth) {
differs = true;
} else {
for (U_32 i = 0; i < targetDepth; ++i) {
if (nodeStack[i].find() != targetStack[i].find()) {
differs = true;
break;
}
}
}
}
if (Log::isEnabled()) {
Log::out() << "Linking13 exception edge from bad monexit at node #"
<< (int) nodeId
<< " to dispatch node #"
<< (int) targetId
<< ::std::endl;
}
linkStacks(nodeDepth, nodeStack,
targetDepth, targetStack,
bottomCliqueRoot);
}
}
if (Log::isEnabled()) {
Log::out() << " done Stage3d" << ::std::endl;
}
badMonitorExits.insert(newBadMonitorExits.begin(), newBadMonitorExits.end());
newBadMonitorExits.clear();
needToCheckAgain = differs;
if (Log::isEnabled()) {
Log::out() << " done Stage3 iteration" << ::std::endl;
}
}
}