void SyncOpt::findBalancedExits_Stage3()

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;
        }
    }
}