Search in sources :

Example 1 with StacksizeAnalysis

use of com.jopdesign.jcopter.analysis.StacksizeAnalysis in project jop by jop-devel.

the class GreedyOptimizer method optimizeMethods.

private void optimizeMethods(AnalysisManager analyses, ExecFrequencyProvider ecp, CandidateSelector selector, Set<MethodInfo> methods) {
    Map<MethodInfo, MethodData> methodData = new LinkedHashMap<MethodInfo, MethodData>(methods.size());
    selector.clear();
    if (maxSteps > 0 && countOptimized >= maxSteps) {
        return;
    }
    // first find and initialize all candidates
    for (MethodInfo method : methods) {
        if (method.isNative())
            continue;
        // to update maxLocals
        method.getCode().compile();
        StacksizeAnalysis stacksize = analyses.getStacksizeAnalysis(method);
        int locals = method.getCode().getMaxLocals();
        for (CodeOptimizer optimizer : optimizers) {
            Collection<Candidate> found;
            found = optimizer.findCandidates(method, analyses, stacksize, locals);
            selector.addCandidates(method, found);
            countCandidates += found.size();
        }
        methodData.put(method, new MethodData(locals));
    }
    // now use the RebateSelector to order the candidates
    selector.sortCandidates(ecp);
    Set<MethodInfo> optimizedMethods = new LinkedHashSet<MethodInfo>();
    Set<MethodInfo> candidateChanges = new LinkedHashSet<MethodInfo>();
    Collection<Candidate> candidates = selector.selectNextCandidates(ecp);
    while (candidates != null) {
        optimizedMethods.clear();
        candidateChanges.clear();
        analyses.clearChangeSets();
        // perform optimization
        for (Candidate c : candidates) {
            MethodInfo method = c.getMethod();
            StacksizeAnalysis stacksize = analyses.getStacksizeAnalysis(method);
            logger.info("Optimizing " + c.toString());
            if (!c.optimize(analyses, stacksize))
                continue;
            countOptimized++;
            if (maxSteps > 0 && countOptimized >= maxSteps) {
                return;
            }
            // to update maxStack and positions
            method.getCode().compile();
            // Now we need to update the stackAnalysis and find new candidates in the optimized code
            List<Candidate> newCandidates = new ArrayList<Candidate>();
            if (c.getStart() != null) {
                stacksize.analyze(c.getStart(), c.getEnd());
                int locals = c.getMaxLocalsInRegion();
                // find new candidates in optimized code
                for (CodeOptimizer optimizer : optimizers) {
                    Collection<Candidate> found;
                    found = optimizer.findCandidates(method, analyses, stacksize, locals, c.getStart(), c.getEnd());
                    newCandidates.addAll(found);
                }
                countCandidates += newCandidates.size();
            }
            // Notify selector to update codesize, remove unreachable methods and to replace
            // old candidates with new ones
            selector.onSuccessfulOptimize(c, newCandidates);
            optimizedMethods.add(method);
        }
        // Now we need to find out for which methods we need to recalculate the candidates..
        // First we add all optimized methods since we added new candidates and changed the codesize
        candidateChanges.addAll(optimizedMethods);
        // small shortcut if we optimize one method at a time. In this case we only have one method to update anyway
        if (methods.size() > 1) {
            // invokeSites, but well..
            for (MethodInfo method : optimizedMethods) {
                candidateChanges.addAll(appInfo.getCallGraph().getDirectInvokers(method));
            }
            // No need to add exec count changes, since candidates calculate values only per single execution,
            // or is there? (cache miss count changes due to exec frequency changes are handled by the cache analysis)
            // We need to find out for which invokeSites the cache-miss-*counts* (as used by
            // Candidate#getDeltaCacheMissCosts()) of invoke and return changed, add to the changeset
            candidateChanges.addAll(analyses.getMethodCacheAnalysis().getClassificationChangeSet());
        }
        // Now let the selector update its analyses and find out which additional methods need sorting
        Set<MethodInfo> changeSet = selector.updateChangeSet(ecp, optimizedMethods, candidateChanges);
        // but only for methods which we optimize.
        for (MethodInfo method : candidateChanges) {
            // skip methods in changeset which are not being optimized
            if (!methodData.containsKey(method))
                continue;
            selector.updateCandidates(method, ecp, analyses.getStacksizeAnalysis(method));
        }
        // Finally use the set of methods for which something changed, and re-sort all candidates of those methods
        if (methods.size() == 1) {
            selector.sortCandidates(ecp, methods);
        } else {
            if (logger.isTraceEnabled()) {
                logger.trace("Sort changes " + changeSet.size());
            }
            selector.sortCandidates(ecp, changeSet);
        }
        // Finally, select the next candidates
        candidates = selector.selectNextCandidates(ecp);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) StacksizeAnalysis(com.jopdesign.jcopter.analysis.StacksizeAnalysis) MethodInfo(com.jopdesign.common.MethodInfo)

Aggregations

MethodInfo (com.jopdesign.common.MethodInfo)1 StacksizeAnalysis (com.jopdesign.jcopter.analysis.StacksizeAnalysis)1 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1