/* * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package org.visage.tools.comp; import com.sun.tools.mjavac.code.Flags; import com.sun.tools.mjavac.util.Context; import com.sun.tools.mjavac.util.Log; import org.visage.tools.code.VisageFlags; import org.visage.tools.code.VisageVarSymbol; import org.visage.tools.util.MsgSym; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; /** * Collect and print statistics on optimization. * * @author Robert Field */ public class VisageOptimizationStatistics { private final Log log; private int instanceVarCount; private int instanceDefCount; private int scriptVarCount; private int scriptDefCount; private int localBoundVarCount; private int localBoundDefCount; private int localUnboundVarCount; private int localUnboundDefCount; private int proxyMethodCount; private int concreteFieldCount; private class DecomposeData implements Comparable { String name; int count; int synthVars; int shreds; DecomposeData(Class tree) { this.name = tree.getSimpleName(); } DecomposeData(String name) { this.name = name; } String name() { return name; } public int compareTo(Object o) { DecomposeData dd = (DecomposeData) o; if (synthVars != dd.synthVars) { return dd.synthVars - synthVars; } else { return name().compareTo(dd.name()); } } } private Stack<DecomposeData> decomposeStack; private DecomposeData unbound; private Map<Class, DecomposeData> decomposeMap; private Map<Class, Integer> translatorMap; /** * Context set-up */ protected static final Context.Key<VisageOptimizationStatistics> visageOptStatKey = new Context.Key<VisageOptimizationStatistics>(); public static VisageOptimizationStatistics instance(Context context) { VisageOptimizationStatistics instance = context.get(visageOptStatKey); if (instance == null) { instance = new VisageOptimizationStatistics(context); } return instance; } protected VisageOptimizationStatistics(Context context) { context.put(visageOptStatKey, this); log = Log.instance(context); instanceVarCount = 0; instanceDefCount = 0; scriptVarCount = 0; scriptDefCount = 0; localBoundVarCount = 0; localBoundDefCount = 0; localUnboundVarCount = 0; localUnboundDefCount = 0; proxyMethodCount = 0; concreteFieldCount = 0; decomposeStack = new Stack<DecomposeData>(); unbound = new DecomposeData("<unbound>"); unbound.count = 1; decomposeStack.push(unbound); decomposeMap = new HashMap<Class, DecomposeData>(); translatorMap = new HashMap<Class, Integer>(); } public void recordDecomposeEnter(Class treeClass) { DecomposeData dd = decomposeMap.get(treeClass); if (dd == null) { dd = new DecomposeData(treeClass); decomposeMap.put(treeClass, dd); } decomposeStack.push(dd); dd.count++; } public void recordDecomposeExit() { decomposeStack.pop(); } public void recordSynthVar(String id) { decomposeStack.peek().synthVars++; } public void recordShreds() { decomposeStack.peek().shreds++; } public void recordTranslator(Class translator) { Integer mCnt = translatorMap.get(translator); int cnt = mCnt==null? 0 : mCnt; translatorMap.put(translator, cnt+1); } public void recordClassVar(VisageVarSymbol vsym) { boolean isDef = vsym.isDef(); boolean isScript = vsym.isStatic(); if (isScript) { if (isDef) { ++scriptDefCount; } else { ++scriptVarCount; } } else { if (isDef) { ++instanceDefCount; } else { ++instanceVarCount; } } } public void recordLocalVar(VisageVarSymbol vsym, boolean isBound, boolean isLocation) { boolean isDef = vsym.isDef(); if (isBound) { if (isDef) { ++localBoundDefCount; } else { ++localBoundVarCount; } } else { if (isDef) { ++localUnboundDefCount; } else { ++localUnboundVarCount; } } } public void recordProxyMethod() { ++proxyMethodCount; } public void recordConcreteField() { ++concreteFieldCount; } private void show(String label, int value) { log.note(MsgSym.MESSAGE_VISAGE_OPTIMIZATION_STATISTIC, label, value); } private void printInstanceVariableData() { int instanceVariableCount = instanceVarCount + instanceDefCount; show("Instance variable count", instanceVariableCount); show("Instance 'var' count", instanceVarCount); show("Instance 'def' count", instanceDefCount); } private void printScriptVariableData() { int scriptVariableCount = scriptVarCount + scriptDefCount; show("Script variable count", scriptVariableCount); show("Script 'var' count", scriptVarCount); show("Script 'def' count", scriptDefCount); } private void printLocalVariableData() { int localBoundVariableCount = localBoundVarCount + localBoundDefCount; show("Local bound variable count", localBoundVariableCount); show("Local bound 'var' count", localBoundVarCount); show("Local bound 'def' count", localBoundDefCount); int localUnboundVariableCount = localUnboundVarCount + localUnboundDefCount; show("Local unbound variable count", localUnboundVariableCount); show("Local unbound 'var' count", localUnboundVarCount); show("Local unbound 'def' count", localUnboundDefCount); int localVariableCount = localBoundVariableCount + localUnboundVariableCount; int localVarCount = localUnboundVarCount + localBoundVarCount; int localDefCount = localUnboundDefCount + localBoundDefCount; show("Local variable count", localVariableCount); show("Local 'var' count", localVarCount); show("Local 'def' count", localDefCount); } private void printProxyMethodData() { show("Proxy method count", proxyMethodCount); } private void printConcreteFieldData() { show("Concrete field count", concreteFieldCount); } private void printTranslators() { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); List<Map.Entry<Class, Integer>> me = new ArrayList(translatorMap.entrySet()); Collections.<Map.Entry<Class, Integer>>sort(me, new Comparator() { public int compare(Object o1, Object o2) { Map.Entry<Class, Integer> e1 = (Map.Entry<Class, Integer>)o1; Map.Entry<Class, Integer> e2 = (Map.Entry<Class, Integer>)o2; int v1 = (int)e1.getValue(); int v2 = (int)e2.getValue(); if (v1==v2) { return e1.getKey().getName().compareTo(e2.getKey().getName()); } else { return v2-v1; } } }); for (Map.Entry<Class, Integer> pair : me) { Class k = pair.getKey(); String name = k.getSimpleName().length()==0? k.getName() : k.getSimpleName(); printWriter.printf("\n%5d %s", (int) pair.getValue(), name); } printWriter.close(); log.note(MsgSym.MESSAGE_VISAGE_OPTIMIZATION_STATISTIC, "Translators", stringWriter.toString()); } private void printDecompose() { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); List<DecomposeData> ldd = new ArrayList(decomposeMap.values()); ldd.add(unbound); Collections.<DecomposeData>sort(ldd); printWriter.println("\n\nSynth Shred Count Synth Shred Tree"); printWriter.println( " All All Per Per "); for (DecomposeData dd : ldd) { printWriter.printf("\n%5d %5d %5d %5.1f %5.1f %s", dd.synthVars, dd.shreds, dd.count, ((double)dd.synthVars)/dd.count, ((double)dd.shreds)/dd.count, dd.name()); } printWriter.close(); log.note(MsgSym.MESSAGE_VISAGE_OPTIMIZATION_STATISTIC, "Decompose", stringWriter.toString()); } public void printData(String which) { if (which.contains("i")) { printInstanceVariableData(); } if (which.contains("s")) { printScriptVariableData(); } if (which.contains("l")) { printLocalVariableData(); } if (which.contains("m")) { printProxyMethodData(); } if (which.contains("f")) { printConcreteFieldData(); } if (which.contains("t")) { printTranslators(); } if (which.contains("d")) { printDecompose(); } } }