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     }