/*
* This file is part of JOP, the Java Optimized Processor
* see <http://www.jopdesign.com/>
*
* Copyright (C) 2011, Stefan Hepp (stefan@stefant.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.jcopter.greedy;
import com.jopdesign.common.MethodInfo;
import com.jopdesign.common.code.CallString;
import com.jopdesign.jcopter.analysis.AnalysisManager;
import com.jopdesign.jcopter.analysis.CodeModification;
import com.jopdesign.jcopter.analysis.ExecFrequencyProvider;
import com.jopdesign.jcopter.analysis.StacksizeAnalysis;
import org.apache.bcel.generic.InstructionHandle;
import java.util.Collection;
/**
* TODO we currently do not account for additional advantages when pairs (or sets) of candidates are optimized.
* We would need to tell the optimizer about
* - possible future candidates, e.g. invoke sites which are created by inlining a method.
* - advantages when optimizing combinations of candidates (from the same optimizer; considering gains when
* candidates of different optimizers are taken into account would be quite tricky), e.g. if all invokesites
* are inlined, we know that we can remove the invokee. We could use the CodeOptimizers to find promising sets
* of candidates, else the candidates would need to provide all the required information to find such sets in a
* generic way.
* - improved WCET-gains when optimizing multiple candidates (this could be done in some generic way).
*
* @author Stefan Hepp (stefan@stefant.org)
*/
public abstract class Candidate implements CodeModification {
private final MethodInfo method;
protected InstructionHandle start;
protected InstructionHandle end;
protected Candidate(MethodInfo method, InstructionHandle start, InstructionHandle end) {
this.method = method;
this.start = start;
this.end = end;
}
/**
* @return the method containing this candidate.
*/
@Override
public MethodInfo getMethod() {
return method;
}
public InstructionHandle getStart() {
return start;
}
public InstructionHandle getEnd() {
return end;
}
/**
* We assume that there is only a single entry edge into this optimized code region. The entry instruction is
* used to check if the optimized code is on the WCET path and to get the execution frequency for the code to optimize.
*
* @return the direct dominator instruction for the optimized code.
*/
public InstructionHandle getEntry() {
return start;
}
public float getHeuristicFactor() {
return 1.0f;
}
/**
* Perform optimization, update start and end instruction handle to the new code.
*
* @param analyses the analyses used by the optimizer.
* @param stacksize the stack analysis for the method to optimize
* @return true if the optimization has been performed.
*/
public abstract boolean optimize(AnalysisManager analyses, StacksizeAnalysis stacksize);
/**
* Update deltaCodesize, deltaLocals and localGain, after some method which may be invoked by the
* affected code has been changed.
*
* <p>This MUST return false if either the stack size or the number of locals exceeds the limits of the
* processor. This MAY return false if the new local codesize exceeds the limits of the processor (but this
* will be checked anyway by the candidate selector).</p>
*
*
* @param analyses the analyses used by the optimizer.
* @param stacksize the stack analysis for the method to optimize.
* @return false if this is not a candidate anymore.
*/
public abstract boolean recalculate(AnalysisManager analyses, StacksizeAnalysis stacksize);
@Override
public Collection<MethodInfo> getUnreachableMethods() {
return null;
}
/**
* To get a few more candidates, we allow for candidates which only work in a set of execution contexts.
* The optimization is only valid if either all other execution contexts are removed (e.g. by inlining or
* callgraph pruning), of if the optimizer creates a copy of the method for all other execution contexts first.
*
* @return a set of callstrings leading to the optimized method for which this optimization is valid, or null
* or an empty set (or a set with a single empty callstring) if this optimization is valid for all callstrings.
*/
public Collection<CallString> getRequiredContext() {
return null;
}
public abstract int getMaxLocalsInRegion();
/**
* TODO in order to support this properly, we need to extend the StacksizeAnalysis with a life range analysis
* for locals (this could use the ValueMapAnalysis).
*
* @return the number of additional local slots required outside the changed code range.
*/
public int getNumPersistentLocals() {
return 0;
}
/**
* @return the expected gain in cycles for a single execution of this code without cache costs
* (i.e. assuming always-hit).
*/
public abstract long getLocalGain();
/**
* Return the expected difference for cache miss costs for a single execution of this code, assuming an
* unknown cache state previous to the execution of the code. This does not need to assume always-miss:
* if a method is invoked twice in the optimized code and the invoker is in an all-fit region, the second
* invoke (and the return from the first invoke!) can be assumed to be a hit, although the first invoke
* must be assumed to be a miss. A negative value means reduced cache miss costs.
*
* <p>This does not include the cache effects due to the increased codesize of the optimized method.</p>
*
* @return the cache miss costs difference assuming an unknown cache state for a single execution for the invokes
* in the optimized code.
* @param analyses
* @param ecp
*/
public abstract long getDeltaCacheMissCosts(AnalysisManager analyses, ExecFrequencyProvider ecp);
@Override
public String toString() {
return getMethod().toString()+"@"+getEntry();
}
}