void SyncOpt::findBalancedExits()

in vm/jitrino/src/optimizer/syncopt.cpp [1782:2020]


void SyncOpt::findBalancedExits(bool optimistic, bool use_IncRecCount)
{
    OpndManager &opndManager = irManager.getOpndManager();
    InstFactory &instFactory = irManager.getInstFactory();

    ControlFlowGraph &fg = irManager.getFlowGraph();
    U_32 numNodes = fg.getMaxNodeId();
    SyncOptDfValue *entrySolution, *exitSolution;
    U_32 numCliques = findBalancedExits_Stage1(optimistic, use_IncRecCount, numNodes,
                                                 entrySolution, exitSolution);

    if (Log::isEnabled()) {
        Log::out() << "numNodes is " << (int) numNodes << ::std::endl;
        Log::out() << "numCliques is " << (int) numCliques << ::std::endl;
    }

    SyncClique *cliquesHeap = new (mm) SyncClique[numCliques];
    SyncClique **entryCliques = new (mm) SyncClique *[numNodes];
    SyncClique **exitCliques = new (mm) SyncClique *[numNodes];
    U_32 cliqueHeapIndex = 0;
    {
        for (U_32 i = 0; i<numNodes; i++) {
            U_32 lin = entrySolution[i].getDepth();
            U_32 lout = exitSolution[i].getDepth();

            entryCliques[i] = &cliquesHeap[cliqueHeapIndex];
            cliqueHeapIndex += lin;
            exitCliques[i] = &cliquesHeap[cliqueHeapIndex];
            cliqueHeapIndex += lout;

            if (Log::isEnabled()) {
                Log::out() << "  node " << (int) i << " has " << (int) lin << " cliques in: [ ";
                for (U_32 j = 0; j<lin; ++j) { 
                    entryCliques[i][j].print(Log::out());
                    Log::out() << " ";
                }
                Log::out() << "]" << ::std::endl;
                
                Log::out() << "  node " << (int) i << " has " << (int) lout << " cliques out: [ ";
                for (U_32 jout = 0; jout<lout; ++jout) { 
                    exitCliques[i][jout].print(Log::out());
                    Log::out() << " ";
                }
                Log::out() << "]" << ::std::endl;
            }
        }
    }
    assert(cliqueHeapIndex <= numCliques);

    if (Log::isEnabled()) {
        Log::out() << "finished dataflow solution" << ::std::endl;
    }

    SyncClique *bottomClique = new (mm) SyncClique();
    if (Log::isEnabled()) {
        Log::out() << "Bottom clique is ";
        bottomClique->print(Log::out());
        Log::out() << ::std::endl;
    }
    
    // process each node and edge (except exception edges) to union monitor cliques
    StlMap<Inst *, StlVectorSet<SyncClique *> *> needRecCount(mm);
    StlMap<Inst *, SyncClique *> monitorCliques(mm);
    findBalancedExits_Stage2(optimistic, use_IncRecCount,
                             entrySolution, exitSolution,
                             bottomClique, entryCliques, exitCliques,
                             needRecCount, monitorCliques);

    // now, each monitorEnter/Exit has an associated clique,
    // and we have applied UnionFind::link to them appropriately (ignoring monexit exceptions)
    // if usereccount, then needRecCount[invalidateInst]=cliques to be incremented
    //    before the invalidating instruction
    // also, needRecCount[monitorExit]=cliques to be invalidated if monitorExit opnd
    //    doesn't match, or if the monitorExit clique is/was invalidated
    SyncClique *bottomCliqueRoot = bottomClique->find();
    if (Log::isEnabled()) {
        Log::out() << "Bottom clique root is ";
        bottomCliqueRoot->print(Log::out());
        Log::out() << ::std::endl;
    }

    // stage 3a

    // stage 3b:
    //   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.

    findBalancedExits_Stage3(optimistic, use_IncRecCount,
                             entrySolution, exitSolution,
                             bottomClique, entryCliques, exitCliques,
                             needRecCount, monitorCliques);
                             
    // at this point, a monitor inst monInst is unbalanced if monitorCliques[monInst] =~ bottom

    // stage 3: Now that we know which cliques are balanceable, modify code.
    //   Other cliques we don't bother with.
    {
        StlMap<Inst *, SyncClique *>::iterator
            miter = monitorCliques.begin(),
            mend = monitorCliques.end();
        for ( ; miter != mend; ++miter) {
            Inst *inst = (*miter).first;
            SyncClique *clique = (*miter).second;

            if (Log::isEnabled()) {
                Log::out() << "Considering balancing instruction: ";
                inst->print(Log::out());
                Log::out() << " with ";
                clique->print(Log::out());
                Log::out() << ::std::endl;
            }

            clique = clique->find();
            if ((clique == bottomCliqueRoot)) {
                if (Log::isEnabled()) {
                    Log::out() << "  Clique == bottom" << ::std::endl;
                }
                continue;
            }
            {
                // we can balance it
                Opnd *obj = inst->getSrc(0);
                assert(obj == clique->opnd);

                VarOpnd *lockVar = getLockVar(obj);
                VarOpnd *oldValueVar = getOldValueOpnd(clique);

                Opnd *lockAddrTmp = opndManager.createSsaTmpOpnd(lockAddrType);
                Opnd *oldValueTmp = opndManager.createSsaTmpOpnd(lockType);

                Opnd *tau = 0;
                switch (inst->getOpcode()) {
                case Op_TauOptimisticBalancedMonitorEnter:
                    if (optimistic) break; // we can ignore this if optimistic, otherwise try to convert it to unoptimistic balmonenter
                    tau = inst->getSrc(2);
                case Op_TauMonitorEnter:
                    {
                        if (!tau)
                            tau = inst->getSrc(1);
                        assert(tau->getType()->tag == Type::Tau);

                        Inst *ldVarLockAddr = instFactory.makeLdVar(lockAddrTmp, lockVar);
                        Inst *balmonenter = (optimistic
                                             ? instFactory.makeTauOptimisticBalancedMonitorEnter(oldValueTmp,
                                                                                                 obj,
                                                                                                 lockAddrTmp,
                                                                                                 tau)
                                             : instFactory.makeTauBalancedMonitorEnter(oldValueTmp,
                                                                                       obj,
                                                                                       lockAddrTmp,
                                                                                       tau));
                        Inst *stVarOldValue = instFactory.makeStVar(oldValueVar, oldValueTmp);
                        ldVarLockAddr->insertAfter(inst);
                        balmonenter->insertAfter(ldVarLockAddr);
                        stVarOldValue->insertAfter(balmonenter);
                        inst->unlink();
                    }
                    break;
                case Op_OptimisticBalancedMonitorExit:
                    if (optimistic) break; // we can ignore this if optimistic, otherwise convert it to un-optimistic balmonexit
                case Op_TauMonitorExit:
                    {
                        Inst *ldVarLockAddr = instFactory.makeLdVar(lockAddrTmp, lockVar);
                        Inst *ldVarOldValue = instFactory.makeLdVar(oldValueTmp, 
                                                                    oldValueVar);
                        Inst *balmonexit = (optimistic
                                            ? instFactory.makeOptimisticBalancedMonitorExit(obj,
                                                                                            lockAddrTmp,
                                                                                            oldValueTmp)
                                            : instFactory.makeBalancedMonitorExit(obj,
                                                                                  lockAddrTmp,
                                                                                  oldValueTmp));
                        ldVarLockAddr->insertAfter(inst);
                        ldVarOldValue->insertAfter(ldVarLockAddr);
                        balmonexit->insertAfter(ldVarOldValue);

                        if (!optimistic) {
                            // remove exception edge
                            Node *node = inst->getNode();
                            Edge* edge = (Edge *)node->getExceptionEdge();
                            assert(edge != NULL);
                            fg.removeEdge(edge);
                        }
                        
                        inst->unlink();
                    }
                    break;
        default:
            break;
                }
            }
        }
    }        
    if (use_IncRecCount) {
        StlVectorSet<SyncClique *> doneCliques(mm);
        StlMap<Inst *, StlVectorSet<SyncClique *> *>::iterator
            miter = needRecCount.begin(),
            mend = needRecCount.end();
        for ( ; miter != mend; ++miter) {
            Inst *invalidatingInst = (*miter).first;
            StlVectorSet<SyncClique *> *cliques = (*miter).second;
            assert(cliques);
            
            if (Log::isEnabled()) {
                Log::out() << "Considering increccount for instruction: ";
                invalidatingInst->print(Log::out());
                Log::out() << ::std::endl;
            }

            doneCliques.clear();

            StlVectorSet<SyncClique *>::iterator
                cliter = cliques->begin(),
                clend = cliques->end();
            for ( ; cliter != clend; ++cliter) {
                SyncClique *thisClique = *cliter;
                thisClique = thisClique->find();
                
                if ((thisClique != bottomCliqueRoot) &&
                    !doneCliques.has(thisClique)) {
                    doneCliques.insert(thisClique);

                    Opnd *obj = thisClique->opnd;
                    assert(obj);

                    // insert incrreccount
                    VarOpnd *oldValueVar = getOldValueOpnd(thisClique);
                    Opnd *oldValueTmp = opndManager.createSsaTmpOpnd(lockType);
                    Inst *ldVarOldValue = instFactory.makeLdVar(oldValueTmp, 
                                                                oldValueVar);
                    Inst *increcInst = instFactory.makeIncRecCount(obj, oldValueTmp);
                    
                    ldVarOldValue->insertBefore(invalidatingInst);
                    increcInst->insertAfter(ldVarOldValue);
                }
            }
        }
    }
}