1 kkz 1.1.2.1 // WriteBarrierStats.java, created Wed Aug 29 16:44:59 2001 by kkz 2 kkz 1.1.2.1 // Copyright (C) 2000 Karen Zee <kkz@tmi.lcs.mit.edu> 3 kkz 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 kkz 1.1.2.1 package harpoon.Analysis.PreciseGC; 5 kkz 1.1.2.1 6 kkz 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 kkz 1.1.2.1 import harpoon.Backend.Generic.Frame; 8 kkz 1.1.2.1 import harpoon.Backend.Maps.NameMap; 9 kkz 1.1.2.1 import harpoon.ClassFile.CachingCodeFactory; 10 kkz 1.1.2.1 import harpoon.ClassFile.HClass; 11 kkz 1.1.2.1 import harpoon.ClassFile.HCode; 12 kkz 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 13 kkz 1.1.2.1 import harpoon.ClassFile.HMethod; 14 kkz 1.5 import harpoon.ClassFile.Linker; 15 kkz 1.1.2.1 import harpoon.IR.Tree.CALL; 16 kkz 1.1.2.1 import harpoon.IR.Tree.Code; 17 kkz 1.1.2.1 import harpoon.IR.Tree.CONST; 18 kkz 1.1.2.1 import harpoon.IR.Tree.DATUM; 19 kkz 1.1.2.1 import harpoon.IR.Tree.DerivationGenerator; 20 kkz 1.1.2.1 import harpoon.IR.Tree.ExpList; 21 kkz 1.1.2.1 import harpoon.IR.Tree.LABEL; 22 kkz 1.1.2.1 import harpoon.IR.Tree.METHOD; 23 kkz 1.1.2.1 import harpoon.IR.Tree.NAME; 24 kkz 1.1.2.1 import harpoon.IR.Tree.Print; 25 kkz 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 26 kkz 1.1.2.1 import harpoon.IR.Tree.SEQ; 27 kkz 1.1.2.1 import harpoon.IR.Tree.Stm; 28 kkz 1.1.2.1 import harpoon.IR.Tree.Tree; 29 kkz 1.1.2.1 import harpoon.IR.Tree.TreeFactory; 30 kkz 1.1.2.1 import harpoon.IR.Tree.TreeKind; 31 kkz 1.1.2.1 import harpoon.IR.Tree.TreeVisitor; 32 kkz 1.1.2.1 import harpoon.Temp.Label; 33 kkz 1.1.2.1 import harpoon.Util.Util; 34 kkz 1.1.2.1 35 kkz 1.1.2.2 import java.io.PrintStream; 36 kkz 1.1.2.2 37 kkz 1.1.2.1 import java.util.Arrays; 38 kkz 1.1.2.1 import java.util.Iterator; 39 kkz 1.1.2.1 import java.util.List; 40 kkz 1.1.2.1 import java.util.HashMap; 41 kkz 1.1.2.1 import java.util.HashSet; 42 kkz 1.1.2.1 import java.util.Map; 43 kkz 1.1.2.1 import java.util.Set; 44 kkz 1.1.2.1 45 kkz 1.1.2.1 46 kkz 1.1.2.1 /** 47 kkz 1.5 * <code>WriteBarrierStats</code> emits data needed for gathering write 48 kkz 1.5 * barrier statistics. This pass will have no effect if 49 kkz 1.5 * <code>WriteBarrierTreePass</code> is also being used. 50 kkz 1.1.2.1 * 51 kkz 1.1.2.1 * @author Karen Zee <kkz@tmi.lcs.mit.edu> 52 cananian 1.6 * @version $Id: WriteBarrierStats.java,v 1.6 2004/02/08 03:20:07 cananian Exp $ 53 kkz 1.1.2.1 */ 54 kkz 1.1.2.1 public class WriteBarrierStats { 55 kkz 1.1.2.1 56 kkz 1.1.2.1 private final CachingCodeFactory ccf; 57 kkz 1.1.2.1 private final HashMap m; 58 kkz 1.1.2.1 private final HashMap cleared; 59 kkz 1.1.2.1 private final CountBarrierVisitor tv; 60 kkz 1.1.2.2 private final PrintStream out; 61 kkz 1.1.2.1 62 kkz 1.1.2.1 /** Creates a <code>WriteBarrierStats</code>, and 63 kkz 1.1.2.1 * performs conversion on all callable methods. 64 kkz 1.1.2.1 */ 65 kkz 1.5 public WriteBarrierStats(Frame f, 66 kkz 1.5 HCodeFactory parent, 67 kkz 1.5 ClassHierarchy ch, 68 kkz 1.5 PrintStream out, 69 kkz 1.5 Linker linker) { 70 kkz 1.1.2.1 this.ccf = new CachingCodeFactory(parent); 71 kkz 1.1.2.1 this.m = new HashMap(); 72 kkz 1.1.2.1 this.cleared = new HashMap(); 73 kkz 1.1.2.2 this.out = out; 74 kkz 1.1.2.1 NameMap nm = f.getRuntime().getNameMap(); 75 kkz 1.5 HClass WBC = linker.forName("harpoon.Runtime.PreciseGC.WriteBarrier"); 76 kkz 1.5 HClass JLO = linker.forName("java.lang.Object"); 77 kkz 1.5 HClass JLRF = linker.forName("java.lang.reflect.Field"); 78 kkz 1.5 final HMethod arraySC = WBC.getMethod("asc", new HClass[] 79 kkz 1.5 {JLO,HClass.Int,JLO,HClass.Int}); 80 kkz 1.5 final HMethod fieldSC = WBC.getMethod("fsc", new HClass[] 81 kkz 1.5 {JLO,JLRF,JLO,HClass.Int}); 82 kkz 1.1.2.1 this.tv = new CountBarrierVisitor(nm.label(arraySC), 83 kkz 1.1.2.2 nm.label(fieldSC), out); 84 kkz 1.1.2.1 // push all methods through 85 cananian 1.6 for(Object hmO : ch.callableMethods()) { 86 cananian 1.6 HMethod hm = (HMethod) hmO; 87 kkz 1.1.2.2 convertOne(ccf, tv, m, hm, out); 88 kkz 1.1.2.1 } 89 kkz 1.1.2.1 } 90 kkz 1.1.2.1 91 kkz 1.5 public HCodeFactory codeFactory() { 92 kkz 1.1.2.1 return new HCodeFactory() { 93 kkz 1.1.2.1 public HCode convert(HMethod hm) { 94 kkz 1.1.2.1 Code c = (Code) ccf.convert(hm); 95 kkz 1.1.2.1 // push through conversion if not yet converted 96 kkz 1.1.2.1 if (m.get(hm) == null) { 97 kkz 1.1.2.2 convertOne(ccf, tv, m, hm, out); 98 kkz 1.1.2.1 // if cleared, fix up count 99 kkz 1.1.2.1 Integer val = (Integer)cleared.remove(hm); 100 kkz 1.1.2.1 if (val != null) tv.count -= val.intValue(); 101 kkz 1.1.2.1 } 102 kkz 1.1.2.1 return c; 103 kkz 1.1.2.1 } 104 kkz 1.1.2.1 public String getCodeName() { return ccf.getCodeName(); } 105 kkz 1.1.2.1 public void clear(HMethod hm) { 106 kkz 1.1.2.1 ccf.clear(hm); 107 kkz 1.1.2.1 // keep track of cleared 108 kkz 1.1.2.1 Integer val = (Integer)m.remove(hm); 109 kkz 1.1.2.1 if (val != null) cleared.put(hm, val); 110 kkz 1.1.2.1 } 111 kkz 1.1.2.1 }; 112 kkz 1.1.2.1 } 113 kkz 1.1.2.1 114 kkz 1.5 /** returns <code>WriteBarrierData</code> object for inserting 115 kkz 1.5 * static data needed to gather dynamic statistics about write 116 kkz 1.5 * barriers. 117 kkz 1.5 */ 118 kkz 1.5 public WriteBarrierData getData(HClass hc, Frame f) { 119 kkz 1.5 return new WriteBarrierData(hc, f, tv.count); 120 kkz 1.1.2.1 } 121 kkz 1.1.2.1 122 kkz 1.1.2.1 // performs a single conversion 123 kkz 1.1.2.1 private static void convertOne(CachingCodeFactory ccf, 124 kkz 1.1.2.1 CountBarrierVisitor tv, 125 kkz 1.1.2.2 Map m, HMethod hm, 126 kkz 1.1.2.2 PrintStream out) { 127 kkz 1.1.2.1 Code c = (Code)ccf.convert(hm); 128 kkz 1.1.2.1 if (c != null) { 129 kkz 1.1.2.1 // grab the count before this method 130 kkz 1.1.2.1 int base = tv.count; 131 kkz 1.1.2.1 Object[] elements = c.getGrapher().getElements(c).toArray(); 132 kkz 1.1.2.1 for(int i = 0; i < elements.length; i++) 133 kkz 1.1.2.1 ((Tree)elements[i]).accept(tv); 134 kkz 1.1.2.1 Object o = m.put(hm, new Integer(tv.count - base)); 135 cananian 1.3.2.1 assert o == null; 136 kkz 1.1.2.2 if (out != null && base != tv.count) { 137 kkz 1.1.2.2 out.println(hm.getDeclaringClass().getName()+"."+ 138 kkz 1.1.2.2 hm.getName()+hm.getDescriptor()); 139 kkz 1.1.2.2 } 140 kkz 1.1.2.1 } 141 kkz 1.1.2.1 } 142 kkz 1.1.2.2 143 kkz 1.1.2.1 // examine Trees 144 kkz 1.1.2.1 private static class CountBarrierVisitor extends TreeVisitor { 145 kkz 1.1.2.2 private final Label LarraySC; 146 kkz 1.1.2.2 private final Label LfieldSC; 147 kkz 1.1.2.2 private final PrintStream out; 148 kkz 1.1.2.2 149 kkz 1.1.2.1 int count = 0; 150 kkz 1.1.2.1 151 kkz 1.1.2.2 CountBarrierVisitor(Label LarraySC, Label LfieldSC, PrintStream out) { 152 kkz 1.1.2.1 this.LarraySC = LarraySC; 153 kkz 1.1.2.1 this.LfieldSC = LfieldSC; 154 kkz 1.1.2.2 this.out = out; 155 kkz 1.1.2.1 } 156 kkz 1.1.2.1 157 kkz 1.1.2.1 public void visit (Tree t) { } 158 kkz 1.1.2.1 159 kkz 1.1.2.1 // only CALLs are relevant 160 kkz 1.1.2.1 public void visit (CALL c) { 161 kkz 1.1.2.1 if (c.getFunc().kind() == TreeKind.NAME) { 162 kkz 1.1.2.1 NAME n = (NAME) c.getFunc(); 163 kkz 1.1.2.1 if (n.label.equals(LarraySC) || n.label.equals(LfieldSC)) { 164 kkz 1.1.2.1 // get last argument 165 kkz 1.1.2.1 ExpList arg = c.getArgs().tail.tail.tail; 166 cananian 1.3.2.1 assert arg.tail == null; 167 kkz 1.1.2.2 if (out != null) { 168 kkz 1.1.2.2 out.println("ID "+count+"\t"+c.getSourceFile()+ 169 kkz 1.1.2.2 "\tline "+c.getLineNumber()); 170 kkz 1.1.2.2 } 171 kkz 1.1.2.1 c.setArgs(ExpList.replace(c.getArgs(), arg.head, new CONST 172 kkz 1.1.2.1 (c.getFactory(), c, count++))); 173 kkz 1.1.2.1 } 174 kkz 1.1.2.1 } 175 kkz 1.1.2.1 } 176 kkz 1.1.2.1 } 177 cananian 1.2 }