use of com.jopdesign.common.code.ExecutionContext in project jop by jop-devel.
the class MethodBuilder method visitInvokeNode.
public void visitInvokeNode(ControlFlowGraph.InvokeNode n) {
ExecutionContext ctx = new ExecutionContext(n.getBasicBlock().getMethodInfo());
MethodCacheAnalysis mca = new MethodCacheAnalysis(jTrans.getProject());
WCETProcessorModel proc = jTrans.getProject().getWCETProcessorModel();
SubAutomaton invokeAuto;
long staticWCET = proc.basicBlockWCET(ctx, n.getBasicBlock());
if (jTrans.getCacheSim().isAlwaysMiss()) {
staticWCET += mca.getInvokeReturnMissCost(n.getInvokeSite(), CallString.EMPTY);
}
invokeAuto = invokeBuilder.translateInvoke(this, n, staticWCET);
this.nodeTemplates.put(n, invokeAuto);
}
use of com.jopdesign.common.code.ExecutionContext in project jop by jop-devel.
the class RebateSelector method initialize.
@Override
public void initialize(GreedyConfig config, boolean dumpStats) {
// calculate current global codesize
globalCodesize = 0;
if (usesCodeRemover) {
for (MethodInfo method : AppInfo.getSingleton().getCallGraph().getMethodInfos()) {
if (!method.hasCode())
continue;
globalCodesize += method.getCode().getNumberOfBytes();
}
} else {
for (ClassInfo cls : AppInfo.getSingleton().getClassInfos()) {
for (MethodInfo method : cls.getMethods()) {
if (!method.hasCode())
continue;
globalCodesize += method.getCode().getNumberOfBytes();
}
}
}
// we need a tie-breaker for the candidate selection, and to make the results deterministic
// so we use a topological order of the (initial) callgraph
DFSVisitor<ExecutionContext, ContextEdge> visitor = new EmptyDFSVisitor<ExecutionContext, ContextEdge>() {
private int counter = 1;
@Override
public void postorder(ExecutionContext node) {
depthMap.put(node.getMethodInfo(), counter++);
}
};
DirectedGraph<ExecutionContext, ContextEdge> graph = analyses.getTargetCallGraph().getReversedGraph();
DFSTraverser<ExecutionContext, ContextEdge> traverser = new DFSTraverser<ExecutionContext, ContextEdge>(visitor);
traverser.traverse(graph);
logger.info("Initial codesize: " + globalCodesize + " bytes");
if (config.doDumpStats() && dumpStats) {
try {
File statsFile = config.getStatsFile();
dump = new PrintWriter(statsFile);
dump.print("total codesize, ");
if (analyses.useWCAInvoker())
dump.print("WCET, ");
dump.println("candidate, ratio, gain, local gain, cache, local cache, delta codesize, frequency");
} catch (FileNotFoundException e) {
throw new AppInfoError("Could not initialize dump file", e);
}
}
}
use of com.jopdesign.common.code.ExecutionContext in project jop by jop-devel.
the class MethodCacheAnalysis method findRemovedMethods.
private Map<ExecutionContext, Set<MethodInfo>> findRemovedMethods(Set<ExecutionContext> roots, Collection<MethodInfo> removed) {
Map<ExecutionContext, Set<MethodInfo>> removeMethods = new LinkedHashMap<ExecutionContext, Set<MethodInfo>>();
LinkedHashSet<ExecutionContext> queue = new LinkedHashSet<ExecutionContext>(roots);
while (!queue.isEmpty()) {
ExecutionContext node = queue.iterator().next();
queue.remove(node);
boolean changed = false;
boolean isRoot = roots.contains(node);
boolean isNew = false;
// we initialize (lazily) by assuming that all removed methods are no longer reachable in any node,
// and then removing entries from the set if they are found to be still reachable.
// This ensures that the size of the sets only decreases and we eventually reach a fixpoint
Set<MethodInfo> set = removeMethods.get(node);
if (set == null) {
set = new LinkedHashSet<MethodInfo>(removed.size());
removeMethods.put(node, set);
for (MethodInfo m : removed) {
// initially add method to remove set if it is reachable from this node
if (reachableMethods.get(node).contains(m)) {
set.add(m);
}
}
changed = true;
isNew = true;
}
// be removed from this node
for (MethodInfo r : removed) {
// already removed
if (!set.contains(r))
continue;
for (ExecutionContext child : callGraph.getChildren(node)) {
// we ignore native methods in the cache analysis
if (child.getMethodInfo().isNative())
continue;
// skip childs which will be removed
if (isRoot && removed.contains(child.getMethodInfo()))
continue;
// TODO this is incorrect for cyclic call graphs.. need to fix this!
if (reachableMethods.get(child).contains(r)) {
set.remove(r);
changed = true;
}
}
}
if (isNew && set.isEmpty()) {
// we did not remove anything here and we did not visit the parents yet, so nothing changes
changed = false;
}
if (changed) {
// we have found more methods, need to update parents
queue.addAll(callGraph.getParents(node));
}
}
return removeMethods;
}
use of com.jopdesign.common.code.ExecutionContext in project jop by jop-devel.
the class MethodCacheAnalysis method updateNodes.
private void updateNodes(SimpleDirectedGraph<ExecutionContext, ContextEdge> closure, Set<ExecutionContext> nodes, boolean reuseResults) {
for (ExecutionContext node : nodes) {
if (node.getMethodInfo().isNative())
continue;
// We could make this more memory efficient, because in many cases we do not need a
// separate set for each node, but this would be more complicated to calculate
Set<MethodInfo> reachable = new LinkedHashSet<MethodInfo>();
reachable.add(node.getMethodInfo());
// we only need to add all children to the set, no need to go down the graph
for (ContextEdge edge : closure.outgoingEdgesOf(node)) {
ExecutionContext target = edge.getTarget();
if (target.getMethodInfo().isNative())
continue;
if (reuseResults && !nodes.contains(target)) {
reachable.addAll(reachableMethods.get(target));
} else {
reachable.add(target.getMethodInfo());
}
}
reachableMethods.put(node, reachable);
}
MethodCache cache = jcopter.getMethodCache();
// now we can sum up the cache blocks for all nodes in the graph
for (ExecutionContext node : nodes) {
if (node.getMethodInfo().isNative())
continue;
Set<MethodInfo> reachable = reachableMethods.get(node);
int blocks = 0;
for (MethodInfo method : reachable) {
int size = MiscUtils.bytesToWords(getMethodSize(method));
blocks += cache.requiredNumberOfBlocks(size);
}
cacheBlocks.put(node, blocks);
}
}
use of com.jopdesign.common.code.ExecutionContext in project jop by jop-devel.
the class MethodCacheAnalysis method inline.
public void inline(CodeModification modification, InvokeSite invokeSite, MethodInfo invokee) {
if (analysisType == AnalysisType.ALWAYS_HIT || analysisType == AnalysisType.ALWAYS_MISS)
return;
Set<ExecutionContext> nodes = new LinkedHashSet<ExecutionContext>();
// We need to go down first, find all new nodes
MethodInfo invoker = invokeSite.getInvoker();
LinkedList<ExecutionContext> queue = new LinkedList<ExecutionContext>(callGraph.getNodes(invoker));
// TODO if the callgraph is compressed, we need to go down all callstring-length long paths
while (!queue.isEmpty()) {
ExecutionContext node = queue.remove();
for (ExecutionContext child : callGraph.getChildren(node)) {
if (!cacheBlocks.containsKey(child) && !nodes.contains(child)) {
nodes.add(child);
queue.add(child);
}
}
}
// update reachable set and codesize for all new nodes
updateNewNodes(nodes);
// To get the old size, use any execution node ..
ExecutionContext node = callGraph.getNodes(invoker).iterator().next();
// this includes all reachable methods, so we need to subtract them
int oldBlocks = cacheBlocks.get(node);
for (MethodInfo m : reachableMethods.get(node)) {
int size = MiscUtils.bytesToWords(getMethodSize(m));
oldBlocks -= cache.requiredNumberOfBlocks(size);
}
int size = MiscUtils.bytesToWords(getMethodSize(invoker));
int newBlocks = cache.requiredNumberOfBlocks(size);
// not using CodeModification codesize delta because it might be an estimation
int deltaBlocks = newBlocks - oldBlocks;
// now go up from the modified method, remove invokee from reachable sets if last invoke was inlined
// and update block counts
findClassificationChanges(invoker, deltaBlocks, modification.getRemovedInvokees(), true);
}
Aggregations