/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * CodeGenerationStats.java * Creation date: Jan 5, 2006 * By: RCypher */ package org.openquark.cal.internal.machine.lecc; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.openquark.cal.compiler.Expression; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.internal.runtime.lecc.LECCMachineConfiguration; /** * A class used to collect statistics about the code generated * by the lecc machine. * @author RCypher */ public class CodeGenerationStats { /** Map of ModuleName -> ModuleStats. Module name to stats for that module. */ private Map<ModuleName, ModuleStats> moduleStats = new HashMap<ModuleName, ModuleStats>(); private ModuleStats currentModuleStats = null; void startNewModule (ModuleName moduleName) { currentModuleStats = new ModuleStats (moduleName.toSourceText()); moduleStats.put (moduleName, currentModuleStats); } void incrementSCArity (int arity) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementSCArity(arity); } void incrementDCArity (int arity) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementDCArity(arity); } void incrementDataType (int nDCs) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementDataType(nDCs); } void incrementLazyPrimOps (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLazyPrimOps(name); } void incrementFullySaturatedDCInLazyContext (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementFullySaturatedDCInLazyContext(name); } void incrementFullySaturatedDCInStrictContext (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementFullySaturatedDCInStrictContext(name); } void incrementFullySaturatedDCInTopLevelContext (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementFullySaturatedDCInTopLevelContext(name); } void incrementOptimizedIfThenElse() { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementOptimizedIfThenElse(); } void incrementStrictDCFieldSelectionCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementStrictDCFieldSelectionCount(); } void incrementLazyDCFieldSelectionCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLazyDCFieldSelectionCount(); } void incrementTopLevelDCFieldSelectionCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementTopLevelDCFieldSelectionCount(); } void incrementDirectForeignCalls () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementDirectForeignCalls(); } void incrementDirectSCCalls () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementDirectSCCalls(); } void incrementLetNonRecCounts (int nVars) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLetNonRecCounts(nVars); } void incrementLetRecCount (int nVars) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLetRecCount(nVars); } void incrementOptimizedAndOr () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementOptimizedAndOr(); } void incrementOptimizedPrimOp (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementOptimizedPrimOp(name); } void incrementNCases (Expression.Switch eSwitch) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementNCases(eSwitch); } void incrementSingleDCCases () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementSingleDCCases(); } void incrementStrictSCNodeCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementStrictSCNodeCount(); } void incrementStrictForeignNodeCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementStrictForeignNodeCount(); } void incrementLazySCNodeCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLazySCNodeCount(); } void incrementLazyForeignNodeCount () { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementLazyForeignNodeCount(); } void incrementTailRecursiveFunctions (int arity) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementTailRecursiveFunctions(arity); } void incrementOptimizedDictionaryApplication (QualifiedName name) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementOptimizedDictionaryApplication(name); } void incrementUnderSaturation (int arity, int nArgs) { if (currentModuleStats == null) { throw new NullPointerException("Attempt to update code generation statistics without a current module."); } currentModuleStats.incrementUnderSaturation(arity, nArgs); } void dumpCodeGenerationStatistics () { String module = System.getProperty(LECCMachineConfiguration.CODE_GENERATION_STATS_PROP); if (module == null) { return; } if (module.equals("")) { module = "all"; } ModuleStats mStats = moduleStats.get(ModuleName.maybeMake(module)); if (mStats == null) { module = module.toLowerCase().trim(); if (module.equals("all") && moduleStats.size() > 0) { mStats = ModuleStats.mergeStats(new ArrayList<ModuleStats>(moduleStats.values())); } } if (mStats == null) { System.out.println("Unable to find code generation statistics for module " + module); } else { mStats.dumpStats(); } } private static class ModuleStats { String moduleNameOrLabel; /** Map of Integer -> Integer. Maps function arity to number of functions with that arity. */ private Map<Integer, Integer> scArities = new HashMap<Integer, Integer>(); /** Map of Integer -> Integer. Maps DC arity to number of DCs with that arity. */ private Map<Integer, Integer> dcArities = new HashMap<Integer, Integer>(); /** Total number of SCs */ private int scCount; /** Total number of DCs */ private int dcCount; /** Total number of data types */ private int dataTypeCount; /** Map of Integer -> Integer. Maps number of non-recursive let vars to number of functions with that many let non-rec. */ private Map<Integer, Integer> letNonRecCounts = new HashMap<Integer, Integer>(); /** Total number on non recursive let variables. */ private int letNonRecCount; /** Map of QualifiedName -> Integer. Maps primitive ops encountered in a lazy context * to the number of occurrences. */ private Map<QualifiedName, Integer> lazyPrimOps = new HashMap<QualifiedName, Integer>(); /** QualifiedName -> Integer. Maps data constructor name to the number of fully saturated occurrences in * a lazy context. */ private Map<QualifiedName, Integer> saturatedDCsInLazyContext = new HashMap<QualifiedName, Integer>(); private int nSaturatedLazyDCs; /** QualifiedName -> Integer. Maps data constructor name to the number of fully saturated occurrences in * a strict context. */ private Map<QualifiedName, Integer> saturatedDCsInStrictContext = new HashMap<QualifiedName, Integer>(); private int nSaturatedStrictDCs; /** QualifiedName -> Integer. Maps data constructor name to the number of fully saturated occurrences in * a top level context. */ private Map<QualifiedName, Integer> saturatedDCsInTopLevelContext = new HashMap<QualifiedName, Integer>(); private int nSaturatedTopLevelDCs; /** QualifiedName -> Integer. Maps primitive op name to the number of instances which are directly evaluated. */ private Map<QualifiedName, Integer> optimizedPrimOps = new HashMap<QualifiedName, Integer>(); /** Count of conditionals that are generated as a java if-then-else. */ private int optimizedIfThenElseCount; /** Count of DC field selections in a strict context. */ private int strictDCFieldSelectionCount; /** Count of DC field selections in a lazy context. */ private int lazyDCFieldSelectionCount; /** Count of DC field selections in a top level context. */ private int topLevelDCFieldSelectionCount; /** Count the number of direct foreign calls generation. */ private int directForeignCallsCount; /** Count the number of SC calls done directly. i.e. fully saturated SC calls in a strict context. */ private int directSCCallsCount; /** Count number of recursive let variables. */ private int letRecVarCount; /** Count of and/or applications that are optimized by generating java && or || */ private int optimizedAndOrCount; /** Integer -> Integer. Maps number of alts to number of cases with that many alts. */ private Map<Integer, Integer> casesByNAlts = new HashMap<Integer, Integer>(); /** String -> Map (Integer -> Integer). Maps tag type to a Map of number of alts to number of cases with that many alts. */ private Map<String, Map<Integer, Integer>> casesByTagType = new HashMap<String, Map<Integer, Integer>>(); /** Total number of cases. */ private int caseCount; /** Number of cases on a data type with only one DC. */ private int singleDCCaseCount; /** Number of fully saturated applications that generate a specialized strict application node. */ private int strictSaturatedSCNodeCount; /** Number of fully saturated foreign applications that generate a specialized strict application node. */ private int strictSaturatedForeignNodeCount; /** Number of fully saturated applications that generate a specialized lazy application node. */ private int lazySaturatedSCNodeCount; /** Number of fully saturated foreign applications that generate a specialized lazy application node. */ private int lazySaturatedForeignNodeCount; /** Integer -> Integer. Maps arity to number of tail recursive functions with that arity. */ private Map<Integer, Integer> nTailRecursiveFunctionsByArity = new HashMap<Integer, Integer>(); /** Total number of tail recursive functions. */ private int tailRecursiveFunctionCount; /** QualifiedName -> Integer. Maps TypeClass name to number of optimized applications. */ private Map<QualifiedName, Integer> optimizedDictionaryApplicationsByTypeClass = new HashMap<QualifiedName, Integer>(); /** Integer -> Integer. Maps number of data constructors to number of data types with that many data constructors. */ private Map<Integer, Integer> dataTypesByNDCs = new HashMap<Integer, Integer>(); /** Integer -> (Map Integer -> Integer) Maps arity to map of # of undersaturated arguments to * number of instances. */ private Map<Integer, Map<Integer, Integer>> underSatMap = new HashMap<Integer, Map<Integer, Integer>>(); ModuleStats (String moduleNameOrLabel) { this.moduleNameOrLabel = moduleNameOrLabel; } void incrementSCArity (int arity) { Integer key = Integer.valueOf(arity); int count = 1; Integer ccount = scArities.get(key); if (ccount != null) { count += ccount.intValue(); } scArities.put(key, Integer.valueOf(count)); scCount++; } void incrementDCArity (int arity) { Integer key = Integer.valueOf(arity); int count = 1; Integer ccount = dcArities.get(key); if (ccount != null) { count += ccount.intValue(); } dcArities.put(key, Integer.valueOf(count)); dcCount++; } void incrementLazyPrimOps (QualifiedName name) { Integer ccount = lazyPrimOps.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } lazyPrimOps.put(name, ccount); } void incrementFullySaturatedDCInLazyContext (QualifiedName name) { Integer ccount = saturatedDCsInLazyContext.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } saturatedDCsInLazyContext.put(name, ccount); nSaturatedLazyDCs++; } void incrementFullySaturatedDCInStrictContext (QualifiedName name) { Integer ccount = saturatedDCsInStrictContext.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } saturatedDCsInStrictContext.put(name, ccount); nSaturatedStrictDCs++; } void incrementFullySaturatedDCInTopLevelContext (QualifiedName name) { Integer ccount = saturatedDCsInTopLevelContext.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } saturatedDCsInTopLevelContext.put(name, ccount); nSaturatedTopLevelDCs++; } void incrementOptimizedIfThenElse() { optimizedIfThenElseCount++; } void incrementStrictDCFieldSelectionCount () { strictDCFieldSelectionCount++; } void incrementLazyDCFieldSelectionCount () { lazyDCFieldSelectionCount++; } void incrementTopLevelDCFieldSelectionCount () { topLevelDCFieldSelectionCount++; } void incrementDirectForeignCalls () { directForeignCallsCount++; } void incrementDirectSCCalls () { directSCCallsCount++; } void incrementLetNonRecCounts (int nVars) { if (nVars == 0) { return; } Integer key = Integer.valueOf(nVars); int count = 1; Integer ccount = letNonRecCounts.get(key); if (ccount != null) { count += ccount.intValue(); } letNonRecCounts.put(key, Integer.valueOf(count)); letNonRecCount += nVars; } void incrementLetRecCount (int nVars) { letRecVarCount++; } void incrementOptimizedAndOr () { optimizedAndOrCount++; } void incrementOptimizedPrimOp (QualifiedName name) { Integer ccount = optimizedPrimOps.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } optimizedPrimOps.put(name, ccount); } void incrementNCases (Expression.Switch eSwitch) { int nAlts = eSwitch.getNAlts(); Object tag = null; for (int i = 0; i < nAlts; ++i) { Expression.Switch.SwitchAlt alt = eSwitch.getAlt(i); if (!alt.isDefaultAlt()) { tag = alt.getFirstAltTag(); break; } } String tagType; if (tag == null) { tagType = "default only"; } else { tagType = tag.getClass().getName(); } // Track cases by number of alts. Integer key = Integer.valueOf(nAlts); int count = 1; Integer ccount = casesByNAlts.get(key); if (ccount != null) { count += ccount.intValue(); } casesByNAlts.put(key, Integer.valueOf(count)); // Track cases by number of alts within tag type. Map<Integer, Integer> casesByNAltsForTag = casesByTagType.get(tagType); if (casesByNAltsForTag == null) { casesByNAltsForTag = new HashMap<Integer, Integer>(); casesByTagType.put (tagType, casesByNAltsForTag); } count = 1; ccount = casesByNAltsForTag.get(key); if (ccount != null) { count += ccount.intValue(); } casesByNAltsForTag.put(key, Integer.valueOf(count)); caseCount++; } void incrementSingleDCCases () { singleDCCaseCount++; } void incrementStrictSCNodeCount () { strictSaturatedSCNodeCount++; } void incrementStrictForeignNodeCount () { strictSaturatedForeignNodeCount++; } void incrementLazySCNodeCount () { lazySaturatedSCNodeCount++; } void incrementLazyForeignNodeCount () { lazySaturatedForeignNodeCount++; } void incrementTailRecursiveFunctions (int arity) { Integer key = Integer.valueOf(arity); int count = 1; Integer ccount = nTailRecursiveFunctionsByArity.get(key); if (ccount != null) { count += ccount.intValue(); } nTailRecursiveFunctionsByArity.put(key, Integer.valueOf(count)); tailRecursiveFunctionCount++; } void incrementOptimizedDictionaryApplication (QualifiedName name) { Integer ccount = optimizedDictionaryApplicationsByTypeClass.get(name); if (ccount == null) { ccount = Integer.valueOf(1); } else { ccount = Integer.valueOf(ccount.intValue() + 1); } optimizedDictionaryApplicationsByTypeClass.put(name, ccount); } void incrementDataType (int nDCs) { Integer key = Integer.valueOf(nDCs); int count = 1; Integer ccount = dataTypesByNDCs.get(key); if (ccount != null) { count += ccount.intValue(); } dataTypesByNDCs.put(key, Integer.valueOf(count)); dataTypeCount++; } void dumpStats () { System.out.println(""); System.out.println("Code generation statistics for module: " + moduleNameOrLabel); System.out.println(""); System.out.println(" Total number of supercombinators: " + scCount); // Display SCs by arity. System.out.println(dumpMap_sortByKey(scArities, "SCs by Arity:", "arity -> count")); System.out.println(""); System.out.println(" Total number of data types: " + dataTypeCount); // Display data types by number of DCs System.out.println(dumpMap_sortByKey(dataTypesByNDCs, "Data types by data constructor count:", "number of DCs -> count")); System.out.println(""); System.out.println(" Total number of data constructors: " + dcCount); // Display DCs by arity. System.out.println(dumpMap_sortByKey(dcArities, "DCs by Arity:", "arity -> count" )); System.out.println(""); // Cases System.out.println(" Total number of cases: " + caseCount); System.out.println(" Number of cases on single DC data type: " + singleDCCaseCount); System.out.println(""); // Cases by number alts by tag type. System.out.println(" Cases by number of alternates, within each tag type: "); List<String> tagTypeList = new ArrayList<String>(casesByTagType.keySet()); Collections.sort(tagTypeList); for (final String tagType : tagTypeList) { Map<Integer, Integer> tagMap = casesByTagType.get(tagType); System.out.println(" Tag: " + tagType); System.out.println(" N Alternates -> Count"); List<Integer> nAltsList = new ArrayList<Integer>(tagMap.keySet()); Collections.sort(nAltsList); for (final Integer key : nAltsList) { Integer value = tagMap.get(key); System.out.println(" " + key.toString() + " -> " + value.toString()); } } System.out.println(""); System.out.println(dumpMap_sortByValue(optimizedPrimOps, "Optimized primitive operation instances", "operation -> Count")); System.out.println(""); System.out.println(dumpMap_sortByValue(lazyPrimOps, "Lazy primitive operation instances", "operation -> Count")); System.out.println(""); System.out.println(" Number of direct foreign calls: " + directForeignCallsCount); System.out.println(" Number of direct SC calls: " + directSCCallsCount); System.out.println(" Number of optimized strict SC application nodes: " + strictSaturatedSCNodeCount); System.out.println(" Number of optimized strict foreign application nodes: " + strictSaturatedForeignNodeCount); System.out.println(" Number of optimized lazy SC application nodes: " + lazySaturatedSCNodeCount); System.out.println(" Number of optimized lazy foreign application nodes: " + lazySaturatedForeignNodeCount); System.out.println(" Number of top level DC field selections: " + topLevelDCFieldSelectionCount); System.out.println(" Number of strict DC field selections: " + strictDCFieldSelectionCount); System.out.println(" Number of lazy DC field selections: " + lazyDCFieldSelectionCount); System.out.println(" Number of optimized conditionals: " + optimizedIfThenElseCount); System.out.println(" Number of optimized &&/||: " + optimizedAndOrCount); System.out.println(""); System.out.println(" Total number of non recursive let variables: " + letNonRecCount); System.out.println(dumpMap_sortByKey(letNonRecCounts, "Number of functions by number of let nonrec.", "# of let vars -> # of functions.")); System.out.println(""); System.out.println(" Total number of tail recursive functions: " + tailRecursiveFunctionCount); System.out.println(dumpMap_sortByKey(nTailRecursiveFunctionsByArity, "Tail recursive functions by arity.", "arity -> Count")); System.out.println(""); System.out.println(" Total number of saturated data construcors in a lazy context: " + nSaturatedLazyDCs); System.out.println(dumpMap_sortByValue(saturatedDCsInLazyContext, "Fully saturated DCs in lazy context.", "name -> count")); System.out.println(""); System.out.println(" Total number of saturated data construcors in a strict context: " + nSaturatedStrictDCs); System.out.println(dumpMap_sortByValue(saturatedDCsInStrictContext, "Fully saturated DCs in strict context.", "name -> count")); System.out.println(""); System.out.println(" Total number of saturated data construcors in a top level context: " + nSaturatedTopLevelDCs); System.out.println(dumpMap_sortByValue(saturatedDCsInTopLevelContext, "Fully saturated DCs in top level context.", "name -> count")); System.out.println(""); // Display SCs by arity. System.out.println(" Undersaturated SC applications"); Object[] keys = underSatMap.keySet().toArray(); Arrays.sort(keys); for (int i = 0, n = keys.length; i < n; ++i) { Object key = keys[i]; System.out.println(" arity = " + key.toString()); Map<Integer, Integer> argMap = underSatMap.get(key); Object[] keys2; Arrays.sort(keys2 = argMap.keySet().toArray()); for(int j = 0, jn = keys2.length; j < jn; ++j) { Object key2 = keys2[j]; Object value = argMap.get(key2); System.out.println(" arg count = " + key2 + ", instances = " + value); } } System.out.println(""); } static private String dumpMap_sortByKey (Map<Integer, Integer> map, String title, String keyName) { StringBuilder sb = new StringBuilder(); sb.append (" " + title + "\n"); sb.append (" " + keyName + "\n"); List<Integer> keyList = new ArrayList<Integer>(map.keySet()); Collections.sort(keyList); for (final Integer key : keyList) { Integer value = map.get(key); sb.append(" " + key.toString() + " -> " + value.toString() + "\n"); } return sb.toString(); } static private <K> String dumpMap_sortByValue (Map<K, Integer> map, String title, String keyName) { StringBuilder sb = new StringBuilder(); sb.append (" " + title + "\n"); sb.append (" " + keyName + "\n"); List<K> keyList = new ArrayList<K>(map.keySet()); List<ObjectPair> pairList = new ArrayList<ObjectPair>(); for (final K key : keyList) { Integer value = map.get(key); pairList.add(new ObjectPair(key, value)); } Collections.sort(pairList); for (final ObjectPair pair : pairList) { sb.append(" " + pair.o1.toString() + " -> " + pair.o2.toString() + "\n"); } return sb.toString(); } private void increment (ModuleStats other) { this.directForeignCallsCount += other.directForeignCallsCount; this.directSCCallsCount += other.directSCCallsCount; this.lazyDCFieldSelectionCount += other.lazyDCFieldSelectionCount; this.lazySaturatedForeignNodeCount += other.lazySaturatedForeignNodeCount; this.lazySaturatedSCNodeCount += other.lazySaturatedSCNodeCount; this.letRecVarCount += other.letRecVarCount; this.optimizedAndOrCount += other.optimizedAndOrCount; this.optimizedIfThenElseCount += other.optimizedIfThenElseCount; this.singleDCCaseCount += other.singleDCCaseCount; this.strictDCFieldSelectionCount += other.strictDCFieldSelectionCount; this.strictSaturatedForeignNodeCount += other.strictSaturatedForeignNodeCount; this.strictSaturatedSCNodeCount += other.strictSaturatedSCNodeCount; this.topLevelDCFieldSelectionCount += other.topLevelDCFieldSelectionCount; this.dataTypeCount += other.dataTypeCount; this.dcCount += other.dcCount; this.scCount += other.scCount; this.caseCount += other.caseCount; this.letNonRecCount += other.letNonRecCount; this.tailRecursiveFunctionCount += other.tailRecursiveFunctionCount; this.nSaturatedLazyDCs += other.nSaturatedLazyDCs; this.nSaturatedStrictDCs += other.nSaturatedStrictDCs; this.nSaturatedTopLevelDCs += other.nSaturatedTopLevelDCs; mergeMapOfInteger (this.casesByNAlts, other.casesByNAlts); mergeMapOfInteger (this.dataTypesByNDCs, other.dataTypesByNDCs); mergeMapOfInteger (this.dcArities, other.dcArities); mergeMapOfInteger (this.lazyPrimOps, other.lazyPrimOps); mergeMapOfInteger (this.letNonRecCounts, other.letNonRecCounts); mergeMapOfInteger (this.nTailRecursiveFunctionsByArity, other.nTailRecursiveFunctionsByArity); mergeMapOfInteger (this.optimizedDictionaryApplicationsByTypeClass, other.optimizedDictionaryApplicationsByTypeClass); mergeMapOfInteger (this.optimizedPrimOps, other.optimizedPrimOps); mergeMapOfInteger (this.saturatedDCsInLazyContext, other.saturatedDCsInLazyContext); mergeMapOfInteger (this.saturatedDCsInStrictContext, other.saturatedDCsInStrictContext); mergeMapOfInteger (this.saturatedDCsInTopLevelContext, other.saturatedDCsInTopLevelContext); mergeMapOfInteger (this.scArities, other.scArities); mergeMapOfMapOfInteger (this.casesByTagType, other.casesByTagType); mergeMapOfMapOfInteger (this.underSatMap, other.underSatMap); } private void incrementUnderSaturation (int arity_, int nArgs_) { Integer arity = Integer.valueOf(arity_); Integer nArgs = Integer.valueOf(nArgs_); Map<Integer, Integer> argMap = underSatMap.get(arity); if (argMap == null) { argMap = new HashMap<Integer, Integer>(); underSatMap.put (arity, argMap); } Integer count = argMap.get(nArgs); if (count == null) { count = Integer.valueOf(1); } else { count = Integer.valueOf(count.intValue()+1); } argMap.put(nArgs, count); } private static <K1, K2> void mergeMapOfMapOfInteger (Map<K1, Map<K2, Integer>> map1, Map<K1, Map<K2, Integer>> map2) { for (final Map.Entry<K1, Map<K2, Integer>> entry : map2.entrySet()) { K1 key = entry.getKey(); Map<K2, Integer> value1 = map1.get(key); Map<K2, Integer> value2 = entry.getValue(); if (value1 == null) { map1.put(key, value2); } else { mergeMapOfInteger(value1, value2); } } } /** * Merge the contents of map2 into map1. * @param map1 * @param map2 */ private static <K> void mergeMapOfInteger (Map<K, Integer> map1, Map<K, Integer> map2) { for (final Map.Entry<K, Integer> entry : map2.entrySet()) { K key = entry.getKey(); Integer value2 = entry.getValue(); Integer value1 = map1.get(key); if (value1 == null) { map1.put(key, value2); } else { map1.put(key, Integer.valueOf(value1.intValue() + value2.intValue())); } } } private static ModuleStats mergeStats (List<ModuleStats> stats) { ModuleStats cumulative = new ModuleStats("all modules"); for (final ModuleStats mStats : stats) { cumulative.increment(mStats); } return cumulative; } } private static class ObjectPair implements Comparable<ObjectPair> { private final Object o1; private final Integer o2; ObjectPair (Object o1, Integer o2) {this.o1 = o1; this.o2 = o2;} public int compareTo (ObjectPair other) { return other.o2.compareTo(o2); } @Override public boolean equals (Object o) { if (o == null || !(o instanceof ObjectPair)) { return false; } ObjectPair other = (ObjectPair)o; return o1.equals(other.o1) && o2.equals(other.o2); } @Override public int hashCode () { return 37 * (17 + o1.hashCode()) + o2.hashCode(); } } }