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      }