1 cananian 1.1.2.1 // SizeCounters.java, created Tue Jul 10 11:27:01 2001 by cananian 2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.SizeOpt; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.Counters.CounterFactory; 7 cananian 1.1.2.1 import harpoon.Analysis.Transformation.MethodMutator; 8 cananian 1.1.2.2 import harpoon.Backend.Generic.Frame; 9 cananian 1.1.2.2 import harpoon.Backend.Generic.Runtime; 10 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 11 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 12 cananian 1.1.2.1 import harpoon.ClassFile.HCodeAndMaps; 13 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 14 cananian 1.1.2.1 import harpoon.ClassFile.HField; 15 cananian 1.1.2.1 import harpoon.IR.Quads.ANEW; 16 cananian 1.1.2.3 import harpoon.IR.Quads.CONST; 17 cananian 1.1.2.1 import harpoon.IR.Quads.Edge; 18 cananian 1.1.2.1 import harpoon.IR.Quads.NEW; 19 cananian 1.1.2.3 import harpoon.IR.Quads.OPER; 20 cananian 1.1.2.3 import harpoon.IR.Quads.Qop; 21 cananian 1.1.2.1 import harpoon.IR.Quads.Quad; 22 cananian 1.1.2.1 import harpoon.IR.Quads.QuadFactory; 23 cananian 1.1.2.3 import harpoon.IR.Quads.QuadNoSSA; 24 cananian 1.1.2.1 import harpoon.IR.Quads.QuadVisitor; 25 cananian 1.1.2.3 import harpoon.Temp.Temp; 26 cananian 1.1.2.6 import harpoon.Util.ArrayIterator; 27 cananian 1.5 import net.cscott.jutil.SnapshotIterator; 28 cananian 1.1.2.3 29 cananian 1.1.2.6 import java.util.Iterator; 30 cananian 1.1.2.1 31 cananian 1.1.2.1 /** 32 cananian 1.1.2.1 * The <code>SizeCounters</code> code factory adds counters for 33 cananian 1.1.2.1 * various allocation properties, to aid in determining the 34 cananian 1.1.2.1 * effectiveness of the various size optimizations in this 35 cananian 1.1.2.1 * package. 36 cananian 1.1.2.1 * 37 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 38 cananian 1.6 * @version $Id: SizeCounters.java,v 1.6 2004/02/08 03:20:22 cananian Exp $ 39 cananian 1.1.2.1 */ 40 cananian 1.3 public class SizeCounters extends MethodMutator<Quad> { 41 cananian 1.1.2.6 final Frame frame; 42 cananian 1.1.2.2 final Runtime.TreeBuilder tb; 43 cananian 1.1.2.6 final BitWidthAnalysis bwa; 44 cananian 1.1.2.1 45 cananian 1.1.2.1 /** Creates a <code>SizeCounters</code>. */ 46 cananian 1.1.2.2 public SizeCounters(HCodeFactory parent, Frame frame) { 47 cananian 1.1.2.6 this(parent, frame, null); 48 cananian 1.1.2.6 } 49 cananian 1.1.2.6 SizeCounters(HCodeFactory parent, Frame frame, BitWidthAnalysis bwa) { 50 cananian 1.1.2.3 super(QuadNoSSA.codeFactory(parent)); 51 cananian 1.1.2.6 this.frame = frame; 52 cananian 1.1.2.2 this.tb = frame.getRuntime().getTreeBuilder(); 53 cananian 1.1.2.6 this.bwa = bwa; 54 cananian 1.1.2.1 } 55 cananian 1.1.2.1 56 cananian 1.3 protected HCode<Quad> mutateHCode(HCodeAndMaps<Quad> input) { 57 cananian 1.3 HCode<Quad> hc = input.hcode(); 58 cananian 1.1.2.1 // prevent instrumentation of the instrumentation code. (sigh) 59 cananian 1.1.2.1 if ("harpoon.Runtime.Counters".equals 60 cananian 1.1.2.1 (hc.getMethod().getDeclaringClass().getName())) 61 cananian 1.1.2.1 return hc; // skip this class. 62 cananian 1.1.2.1 // total allocation counter. 63 cananian 1.1.2.1 Visitor v = new Visitor(hc); 64 cananian 1.4 // use snapshot while visiting so as not to confuse iterator 65 cananian 1.4 for (Iterator<Quad> it=new SnapshotIterator<Quad> 66 cananian 1.4 (hc.getElementsI()); it.hasNext(); ) 67 cananian 1.4 it.next().accept(v); 68 cananian 1.1.2.1 // done! 69 cananian 1.1.2.1 return hc; 70 cananian 1.1.2.1 } 71 cananian 1.1.2.1 private class Visitor extends QuadVisitor { 72 cananian 1.1.2.1 final QuadFactory qf; 73 cananian 1.3 Visitor(HCode<Quad> hc) { qf=hc.getRootElement().getFactory(); } 74 cananian 1.1.2.1 public void visit(Quad q) { /* do nothing */ } 75 cananian 1.1.2.1 public void visit(ANEW q) { 76 cananian 1.1.2.4 // do not insert code if none of the relevant counters are enabled. 77 cananian 1.1.2.4 if (!enabled(q.hclass(), q.dimsLength())) return; 78 cananian 1.1.2.4 // okay, we have to calculate array lengths & whatnot. 79 cananian 1.1.2.1 Edge e = q.prevEdge(0); 80 cananian 1.1.2.3 HClass type = q.hclass(); 81 cananian 1.1.2.3 Temp Tc = new Temp(qf.tempFactory(), "cntA"); 82 cananian 1.1.2.3 Temp Tl = new Temp(qf.tempFactory(), "cntB"); 83 cananian 1.1.2.3 e = addAt(e, new CONST(qf, null, Tc, new Long(1), HClass.Long)); 84 cananian 1.1.2.3 for (int i=0; i<q.dimsLength(); i++) { 85 cananian 1.1.2.4 type = type.getComponentType(); 86 cananian 1.1.2.3 // Tc contains how *many* arrays of this type 87 cananian 1.1.2.3 // Tl will contain total *length* of these arrays. 88 cananian 1.1.2.3 e = addAt(e, new OPER(qf, null, Qop.I2L, Tl, 89 cananian 1.1.2.3 new Temp[] { q.dims(i) } )); 90 cananian 1.1.2.3 e = addAt(e, new OPER(qf, null, Qop.LMUL, Tl, 91 cananian 1.1.2.3 new Temp[] { Tc, Tl } )); 92 cananian 1.1.2.4 // add counters 93 cananian 1.1.2.4 e = CounterFactory.spliceIncrement 94 cananian 1.1.2.4 (qf, e, arrayprefix(type)+".count", Tc, true/*long*/); 95 cananian 1.1.2.4 e = CounterFactory.spliceIncrement 96 cananian 1.1.2.4 (qf, e, arrayprefix(type)+".length", Tl, true/*long*/); 97 cananian 1.1.2.8 // pointer bytes. 98 cananian 1.1.2.8 if (!type.isPrimitive()) // this is an object array 99 cananian 1.1.2.8 e = CounterFactory.spliceIncrement 100 cananian 1.1.2.8 (qf, e, "sizecnt.array.pointer.words",Tl,true/*long*/); 101 cananian 1.1.2.3 // swap Tl and Tc 102 cananian 1.1.2.3 { Temp t=Tl; Tl=Tc; Tc=t; } 103 cananian 1.1.2.3 // new type. 104 cananian 1.1.2.3 } 105 cananian 1.1.2.3 // done. 106 cananian 1.1.2.3 } 107 cananian 1.1.2.4 private String arrayprefix(HClass component_type) { 108 cananian 1.1.2.3 String typename = component_type.isPrimitive() ? 109 cananian 1.1.2.3 component_type.getName() : "object"; 110 cananian 1.1.2.4 return "sizecnt.array."+typename; 111 cananian 1.1.2.4 } 112 cananian 1.1.2.4 private boolean enabled(HClass arraytype, int dims) { 113 cananian 1.1.2.4 HClass type = arraytype.getComponentType(); 114 cananian 1.1.2.4 for (int i=0; i<dims; i++, type = type.getComponentType()) 115 cananian 1.1.2.4 if (CounterFactory.isEnabled(arrayprefix(type)+".count") || 116 cananian 1.1.2.4 CounterFactory.isEnabled(arrayprefix(type)+".length")) 117 cananian 1.1.2.4 return true; 118 cananian 1.1.2.4 return false; 119 cananian 1.1.2.1 } 120 cananian 1.1.2.3 121 cananian 1.1.2.1 public void visit(NEW q) { 122 cananian 1.1.2.1 Edge e = q.prevEdge(0); 123 cananian 1.1.2.4 e = CounterFactory.spliceIncrement(qf, e, "sizecnt.object.count"); 124 cananian 1.1.2.2 int size = tb.headerSize(q.hclass())+tb.objectSize(q.hclass()); 125 cananian 1.1.2.4 e = CounterFactory.spliceIncrement(qf, e, 126 cananian 1.1.2.4 "sizecnt.object.size."+size); 127 cananian 1.1.2.5 e = CounterFactory.spliceIncrement 128 cananian 1.1.2.6 (qf, e, "sizecnt.count_by_type."+q.hclass().getName()); 129 cananian 1.1.2.6 e = CounterFactory.spliceIncrement 130 cananian 1.1.2.5 (qf, e, "sizecnt.bytes_by_type."+q.hclass().getName(), size); 131 cananian 1.1.2.8 // how many pointer words allocated in objects? 132 cananian 1.1.2.8 int pntr = 0; 133 cananian 1.1.2.8 for (HClass hc=q.hclass(); hc!=null; hc=hc.getSuperclass()) { 134 cananian 1.6 for (HField hf : hc.getDeclaredFields()) { 135 cananian 1.1.2.8 if (hf.isStatic() || hf.getType().isPrimitive()) continue; 136 cananian 1.1.2.8 pntr++; 137 cananian 1.1.2.8 } 138 cananian 1.1.2.8 } 139 cananian 1.1.2.8 e = CounterFactory.spliceIncrement 140 cananian 1.1.2.8 (qf, e, "sizecnt.object.pointer.words", pntr); 141 cananian 1.1.2.6 // special bitwidth-aware counters. 142 cananian 1.1.2.6 if (bwa!=null) { 143 cananian 1.1.2.7 int bits=0, rounded_bits=0; 144 cananian 1.1.2.10 int unread_bits=0, unread_rounded_bits=0; 145 cananian 1.1.2.10 int const_bits=0, const_rounded_bits=0; 146 cananian 1.1.2.6 for (HClass hc=q.hclass(); hc!=null; hc=hc.getSuperclass()) { 147 cananian 1.6 for (HField hf : hc.getDeclaredFields()) { 148 cananian 1.1.2.6 if (hf.isStatic()) continue; 149 cananian 1.1.2.7 int mybits; 150 cananian 1.1.2.6 if (hf.getType()==HClass.Float) 151 cananian 1.1.2.7 mybits = 32; 152 cananian 1.1.2.6 else if (hf.getType()==HClass.Double) 153 cananian 1.1.2.7 mybits = 64; 154 cananian 1.1.2.7 else if (!hf.getType().isPrimitive()) 155 cananian 1.1.2.7 mybits = frame.pointersAreLong() ? 64 : 32; 156 cananian 1.1.2.6 else 157 cananian 1.1.2.7 mybits = Math.max(bwa.plusWidthMap(hf), 158 cananian 1.1.2.7 bwa.minusWidthMap(hf)); 159 cananian 1.1.2.10 int rounded_mybits = ((mybits+7)/8)*8; 160 cananian 1.1.2.10 if (bwa.isConst(hf)) { // field is constant! 161 cananian 1.1.2.10 const_bits += mybits; 162 cananian 1.1.2.10 const_rounded_bits += rounded_mybits; 163 cananian 1.1.2.10 } else if (!bwa.isRead(hf)) { // field is unread! 164 cananian 1.1.2.10 unread_bits += mybits; 165 cananian 1.1.2.10 unread_rounded_bits += rounded_mybits; 166 cananian 1.1.2.10 } else { 167 cananian 1.1.2.10 bits += mybits; 168 cananian 1.1.2.10 rounded_bits += rounded_mybits; 169 cananian 1.1.2.10 } 170 cananian 1.1.2.6 } 171 cananian 1.1.2.6 } 172 cananian 1.1.2.10 // count constant, unread, and other bits. 173 cananian 1.1.2.6 e = CounterFactory.spliceIncrement 174 cananian 1.1.2.10 (qf,e, "sizecnt.bits_by_type."+q.hclass().getName(),bits); 175 cananian 1.1.2.7 e = CounterFactory.spliceIncrement 176 cananian 1.1.2.10 (qf,e, "sizecnt.const_bits_by_type."+q.hclass().getName(), 177 cananian 1.1.2.10 const_bits); 178 cananian 1.1.2.10 e = CounterFactory.spliceIncrement 179 cananian 1.1.2.10 (qf,e, "sizecnt.unread_bits_by_type."+q.hclass().getName(), 180 cananian 1.1.2.10 unread_bits); 181 cananian 1.1.2.10 // also byte-rounded versions of the same. 182 cananian 1.1.2.10 e = CounterFactory.spliceIncrement 183 cananian 1.1.2.10 (qf, e, 184 cananian 1.1.2.10 "sizecnt.rounded_bits_by_type."+q.hclass().getName(), 185 cananian 1.1.2.10 rounded_bits); 186 cananian 1.1.2.10 e = CounterFactory.spliceIncrement 187 cananian 1.1.2.10 (qf, e, 188 cananian 1.1.2.11 "sizecnt.const_rounded_bits_by_type."+q.hclass().getName(), 189 cananian 1.1.2.10 const_rounded_bits); 190 cananian 1.1.2.10 e = CounterFactory.spliceIncrement 191 cananian 1.1.2.10 (qf, e, 192 cananian 1.1.2.11 "sizecnt.unread_rounded_bits_by_type."+q.hclass().getName(), 193 cananian 1.1.2.10 unread_rounded_bits); 194 cananian 1.1.2.6 } 195 cananian 1.1.2.1 } 196 cananian 1.1.2.1 } 197 cananian 1.1.2.3 // private helper functions. 198 cananian 1.1.2.3 private static Edge addAt(Edge e, Quad q) { return addAt(e, 0, q, 0); } 199 cananian 1.1.2.3 private static Edge addAt(Edge e, int which_pred, Quad q, int which_succ) { 200 cananian 1.3 Quad frm = e.from(); int frm_succ = e.which_succ(); 201 cananian 1.3 Quad to = e.to(); int to_pred = e.which_pred(); 202 cananian 1.1.2.3 Quad.addEdge(frm, frm_succ, q, which_pred); 203 cananian 1.1.2.3 Quad.addEdge(q, which_succ, to, to_pred); 204 cananian 1.1.2.3 return to.prevEdge(to_pred); 205 cananian 1.1.2.3 } 206 cananian 1.2 }