/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2010, Benedikt Huber (benedikt.huber@gmail.com) * * 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.wcet.jop; import com.jopdesign.common.AppInfo; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.code.BasicBlock; import com.jopdesign.common.code.ControlFlowGraph; import com.jopdesign.common.code.ControlFlowGraph.CFGNode; import com.jopdesign.wcet.WCETTool; import org.apache.bcel.Constants; import org.apache.bcel.generic.CPInstruction; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.FieldInstruction; import org.apache.bcel.generic.Instruction; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InvokeInstruction; import org.apache.bcel.generic.ObjectType; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; public class ConstantCache { private WCETTool project; private Map<MethodInfo, Set<Integer>> cpoolAddressMap = new HashMap<MethodInfo, Set<Integer>>(); private Map<MethodInfo, Set<Integer>> staticAddressMap = new HashMap<MethodInfo, Set<Integer>>(); private void addAddress(Map<MethodInfo, Set<Integer>> map, MethodInfo mi, int address) { if (!map.containsKey(mi)) { map.put(mi, new TreeSet<Integer>()); } map.get(mi).add(address); } public ConstantCache(WCETTool project) { this.project = project; } public ConstantCache build() { List<MethodInfo> methods = project.getCallGraph().getReachableImplementations(project.getTargetMethod()); for (int i = methods.size() - 1; i >= 0; i--) { MethodInfo mi = methods.get(i); ControlFlowGraph cfg = project.getFlowGraph(mi); for (CFGNode n : cfg.vertexSet()) { BasicBlock bb = n.getBasicBlock(); if (bb == null) continue; for (InstructionHandle ii : bb.getInstructions()) { extractConstantAddresses(cfg, ii); } } } return this; } /* Prototyping ... */ /** * PROTOTYPE status: Find the set of non-heap addresses that might be accessed by the instruction handle * * @param cfg * @param ih * @return */ private void extractConstantAddresses(ControlFlowGraph cfg, InstructionHandle ih) { Instruction ii = ih.getInstruction(); switch (ii.getOpcode()) { case Constants.PUTSTATIC: case Constants.GETSTATIC: addStaticFieldAddress(cfg, (FieldInstruction) ii); break; case Constants.LDC: case Constants.LDC_W: case Constants.LDC2_W: addConstantPoolAddress(cfg, (CPInstruction) ii); break; default: if (ii instanceof InvokeInstruction) { addConstantPoolAddress(cfg, (InvokeInstruction) ii); } break; } } private void addStaticFieldAddress(ControlFlowGraph cfg, FieldInstruction fii) { AppInfo appInfo = cfg.getAppInfo(); ConstantPoolGen cpg = cfg.getMethodInfo().getConstantPoolGen(); String fieldName = fii.getFieldName(cpg) + fii.getSignature(cpg); Integer address = project.getLinkerInfo().getStaticFieldAddress( ((ObjectType) fii.getReferenceType(cpg)).getClassName(), fieldName); addAddress(staticAddressMap, cfg.getMethodInfo(), address); } private void addConstantPoolAddress(ControlFlowGraph cfg, CPInstruction ii) { AppInfo appInfo = cfg.getAppInfo(); LinkerInfo linker = project.getLinkerInfo(); Integer address = linker.getLinkInfo(cfg.getMethodInfo().getClassInfo()).getConstAddress(ii.getIndex()); addAddress(cpoolAddressMap, cfg.getMethodInfo(), address); } public void dumpStats() { System.out.println("Static addresses"); Set<Integer> allStatics = new TreeSet<Integer>(); for (Entry<MethodInfo, Set<Integer>> addressEntry : staticAddressMap.entrySet()) { System.out.print(" " + addressEntry.getKey().getFQMethodName()); for (int address : addressEntry.getValue()) { System.out.print(String.format(" 0x%x", address)); allStatics.add(address); } System.out.println(); } System.out.println(" Total: " + allStatics.size()); System.out.println("Constant Pool addresses"); Set<Integer> allConsts = new TreeSet<Integer>(); for (Entry<MethodInfo, Set<Integer>> addressEntry : cpoolAddressMap.entrySet()) { System.out.print(" " + addressEntry.getKey().getFQMethodName()); for (int address : addressEntry.getValue()) { System.out.print(String.format(" 0x%x", address)); allConsts.add(address); } System.out.println(); } System.out.println(" Total: " + allConsts.size()); } }