/* * 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.allocation; import com.jopdesign.common.ClassInfo; import com.jopdesign.common.FieldInfo; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.code.BasicBlock; import com.jopdesign.common.code.ExecutionContext; import com.jopdesign.common.code.LoopBound; import com.jopdesign.dfa.analyses.Interval; import com.jopdesign.wcet.WCETProcessorModel; import com.jopdesign.wcet.WCETTool; import com.jopdesign.wcet.annotations.SourceAnnotations; import com.jopdesign.wcet.jop.CacheModel; import com.jopdesign.wcet.jop.MethodCache; import com.jopdesign.wcet.jop.NoMethodCache; import com.jopdesign.wcet.jop.ObjectCache; import org.apache.bcel.Constants; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.MULTIANEWARRAY; import org.apache.bcel.generic.NEW; import org.apache.bcel.generic.NEWARRAY; import org.apache.bcel.generic.ObjectType; import org.apache.bcel.generic.Type; import java.util.Collections; import java.util.LinkedList; import java.util.List; public abstract class AllocationWcetModel implements WCETProcessorModel { protected WCETTool project; public AllocationWcetModel(WCETTool p) { project = p; } public String getName() { return "allocation"; } public long basicBlockWCET(ExecutionContext ctx, BasicBlock bb) { int size = 0; for(InstructionHandle ih : bb.getInstructions()) { size += getExecutionTime(ctx, ih); } return size; } public long getExecutionTime(ExecutionContext context, InstructionHandle ih) { int opcode = ih.getInstruction().getOpcode(); MethodInfo mCtx = context.getMethodInfo(); if (opcode == Constants.NEW) { NEW insn = (NEW)ih.getInstruction(); ObjectType type = insn.getLoadClassType(mCtx.getConstantPoolGen()); return computeObjectSize(getFieldSize(getObjectFields(type.getClassName()))); } else if (opcode == Constants.NEWARRAY || opcode == Constants.ANEWARRAY) { int typeSize = 1; if (ih.getInstruction() instanceof NEWARRAY) { NEWARRAY insn = (NEWARRAY)ih.getInstruction(); if (insn.getTypecode() == Constants.T_DOUBLE || insn.getTypecode() == Constants.T_LONG) { typeSize = 2; } } return computeArraySize(getArrayBound(context, ih, 0)*typeSize); } else if (opcode == Constants.MULTIANEWARRAY) { MULTIANEWARRAY insn = (MULTIANEWARRAY)ih.getInstruction(); int dim = insn.getDimensions(); long count = 1; long size = 0; for (int i = dim-1; i >= 0; i--) { long bound = getArrayBound(context, ih, i); size += count * computeArraySize(bound); count *= bound; } return size; } else { return 0; } } private long getArrayBound(ExecutionContext context, InstructionHandle ih, int index) { int srcLine = context.getMethodInfo().getCode().getLineNumberTable().getSourceLine(ih.getPosition()); // get annotated size LoopBound annotated = null; try { SourceAnnotations annots = project.getAnnotations(context.getMethodInfo().getClassInfo()); annotated = annots.annotationsForLine(srcLine); if (annotated == null) { WCETTool.logger.info("No annotated bound for array at " + context + ":" + srcLine); } } catch (Exception exc) { // TODO: anything else to do? WCETTool.logger.warn("Problem reading annotated bound for array at " + context + ":" + srcLine, exc); } // get analyzed size Interval analyzed = null; Interval [] sizes = null; if (project.getDfaLoopBounds() != null) { sizes = project.getDfaLoopBounds().getArraySizes(ih, context.getCallString()); } if (sizes == null) { WCETTool.logger.info("No DFA available for array at " + context + ":" + srcLine); } else { analyzed = sizes[index]; if (analyzed == null) { WCETTool.logger.info("No DFA bound for array at " + context + ":" + srcLine); } } // compute which bound to use if (analyzed != null && analyzed.hasUb()) { if (annotated != null) { if (annotated.getUpperBound(context) > analyzed.getUb()) { WCETTool.logger.warn("DFA bound smaller than annotated bound for array at " + context + ":" + srcLine); } if (annotated.getUpperBound(context) < analyzed.getUb()) { WCETTool.logger.warn("DFA bound larger than annotated bound for array at " + context + ":" + srcLine); } if (annotated.getUpperBound(context) == analyzed.getUb()) { WCETTool.logger.info("DFA bound equals annotated bound for array at " + context + ":" + srcLine); } return Math.max(annotated.getUpperBound(context), analyzed.getUb()); } else { return analyzed.getUb(); } } else { if (annotated != null) { return annotated.getUpperBound(context); } else { WCETTool.logger.error("Cannot determine cost of unbounded array " + context.getMethodInfo().getFQMethodName() + ":" + srcLine + ".\nApproximating with 1024 words, but result is not safe anymore."); return 1024; } } } public abstract long computeObjectSize(long raw); public abstract long computeArraySize(long raw); public List<Type> getObjectFields(String className) { List<Type> l = new LinkedList<Type>(); ClassInfo cli = project.getAppInfo().getClassInfo(className); if (cli.getSuperClassName() != null) { l.addAll(getObjectFields(cli.getSuperClassName())); } for (FieldInfo f : cli.getFields()) { if (!f.isStatic()) { l.add(f.getType()); } } return l; } public int getFieldSize(List<Type> fields) { int size = 0; for (Type t : fields) { size += t.getSize(); } return size; } @Override public MethodCache getMethodCache() { return new NoMethodCache(); } @Override public ObjectCache getObjectCache() { return null; } @Override public List<CacheModel> getCaches() { return Collections.emptyList(); } }