1 cananian 1.1.2.1 // MZFWidenType.java, created Tue Nov 13 00:23:59 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.Transformation.MethodMutator;
  7 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  8 cananian 1.1.2.1 import harpoon.ClassFile.HCode;
  9 cananian 1.1.2.1 import harpoon.ClassFile.HCodeAndMaps;
 10 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory;
 11 cananian 1.1.2.1 import harpoon.ClassFile.HField;
 12 cananian 1.1.2.2 import harpoon.ClassFile.HFieldMutator;
 13 cananian 1.1.2.2 import harpoon.ClassFile.HMethod;
 14 cananian 1.1.2.2 import harpoon.ClassFile.HMethodMutator;
 15 cananian 1.1.2.1 import harpoon.ClassFile.Linker;
 16 cananian 1.1.2.1 import harpoon.IR.Quads.ANEW;
 17 cananian 1.1.2.1 import harpoon.IR.Quads.INSTANCEOF;
 18 cananian 1.1.2.1 import harpoon.IR.Quads.Quad;
 19 cananian 1.1.2.1 import harpoon.IR.Quads.QuadVisitor;
 20 cananian 1.1.2.1 import harpoon.IR.Quads.TYPESWITCH;
 21 cananian 1.8     import net.cscott.jutil.Default.PairList;
 22 cananian 1.1.2.1 import harpoon.Util.HClassUtil;
 23 cananian 1.8     import net.cscott.jutil.SnapshotIterator;
 24 cananian 1.1.2.1 import harpoon.Util.Util;
 25 cananian 1.1.2.1 
 26 cananian 1.1.2.2 import java.util.Arrays;
 27 cananian 1.6     import java.util.HashSet;
 28 cananian 1.1.2.2 import java.util.Iterator;
 29 cananian 1.1.2.1 import java.util.List;
 30 cananian 1.1.2.1 import java.util.Map;
 31 cananian 1.1.2.2 import java.util.Set;
 32 cananian 1.1.2.1 /**
 33 cananian 1.1.2.1  * <code>MZFWidenType</code> widens the types mentioned in
 34 cananian 1.1.2.1  * <code>ANEW</code>, <code>INSTANCEOF</code>, and <code>TYPESWITCH</code>
 35 cananian 1.1.2.1  * quads so that they play nicely with the split types generated by
 36 cananian 1.1.2.2  * <code>MZFCompressor</code>.  It also widens types mentioned in
 37 cananian 1.1.2.2  * field and method signatures.
 38 cananian 1.1.2.1  * 
 39 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 40 cananian 1.9      * @version $Id: MZFWidenType.java,v 1.9 2004/02/08 03:20:22 cananian Exp $
 41 cananian 1.1.2.1  */
 42 cananian 1.5     class MZFWidenType extends MethodMutator<Quad> {
 43 cananian 1.1.2.1     /** the linker to use */
 44 cananian 1.1.2.1     final Linker linker;
 45 cananian 1.1.2.1     /** a map from HClasses to a list of sorted fields; the splitting has
 46 cananian 1.1.2.1      *  been done in the order of the list. */
 47 cananian 1.7         final Map<HClass,List<PairList<HField,Number>>> listmap;
 48 cananian 1.1.2.1     /** a map from <code>HField</code>s to the <code>HClass</code> which
 49 cananian 1.1.2.1      *  eliminates that field. */
 50 cananian 1.5         final Map<HField,HClass> field2class;
 51 cananian 1.1.2.1     /** Creates a <code>MZFWidenType</code>. */
 52 cananian 1.1.2.1     public MZFWidenType(HCodeFactory hcf,
 53 cananian 1.5                             Linker linker,
 54 cananian 1.7                             Map<HClass,List<PairList<HField,Number>>> listmap,
 55 cananian 1.5                             Map<HField,HClass> field2class,
 56 cananian 1.5                             Set<HMethod> callableMethods, Set<HClass> allClasses) {
 57 cananian 1.1.2.1         super(hcf);
 58 cananian 1.1.2.1         this.linker = linker;
 59 cananian 1.1.2.1         this.listmap = listmap;
 60 cananian 1.1.2.1         this.field2class = field2class;
 61 cananian 1.1.2.2         // widen parameter and return types of all callable methods.
 62 cananian 1.3.2.2         // (also, of all interfaces which these callable methods implement,
 63 cananian 1.3.2.2         //  and all superclass methods which these callable methods override)
 64 cananian 1.9             for (HMethod hm : allMethods(allClasses)) {
 65 cananian 1.1.2.2             hm.getMutator().setReturnType(widen(hm.getReturnType()));
 66 cananian 1.1.2.2             HClass[] paramTypes = hm.getParameterTypes();
 67 cananian 1.1.2.2             for (int i=0; i<paramTypes.length; i++)
 68 cananian 1.1.2.2                 if (widen(paramTypes[i])!=paramTypes[i])
 69 cananian 1.1.2.2                     hm.getMutator().setParameterType(i, widen(paramTypes[i]));
 70 cananian 1.1.2.2         }
 71 cananian 1.1.2.2         // widen types of all fields
 72 cananian 1.9             for (HClass hc : allClasses) {
 73 cananian 1.1.2.2             HField[] hfa = hc.getDeclaredFields();
 74 cananian 1.1.2.2             for (int i=0; i<hfa.length; i++)
 75 cananian 1.1.2.2                 if (widen(hfa[i].getType())!=hfa[i].getType())
 76 cananian 1.1.2.2                     hfa[i].getMutator().setType(widen(hfa[i].getType()));
 77 cananian 1.1.2.2         }
 78 cananian 1.1.2.1     }
 79 cananian 1.5         private Set<HMethod> allMethods(Set<HClass> allClasses) {
 80 cananian 1.5             Set<HMethod> result = new HashSet<HMethod>();
 81 cananian 1.9             for (HClass hc : allClasses) {
 82 cananian 1.3.2.2             result.addAll(Arrays.asList(hc.getMethods()));
 83 cananian 1.3.2.2         }
 84 cananian 1.3.2.2         return result;
 85 cananian 1.1.2.1     }
 86 cananian 1.5         protected HCode<Quad> mutateHCode(HCodeAndMaps<Quad> input) {
 87 cananian 1.5             HCode<Quad> hc = input.hcode();
 88 cananian 1.1.2.1         QuadVisitor qv = new QuadVisitor() {
 89 cananian 1.1.2.1                 public void visit(Quad q) { /* booring. */ }
 90 cananian 1.1.2.1                 public void visit(ANEW q) {
 91 cananian 1.1.2.1                     Quad.replace
 92 cananian 1.1.2.1                         (q, new ANEW(q.getFactory(), q, q.dst(),
 93 cananian 1.1.2.1                                      widen(q.hclass()), q.dims()));
 94 cananian 1.1.2.1                 }
 95 cananian 1.1.2.1                 public void visit(INSTANCEOF q) {
 96 cananian 1.1.2.1                     Quad.replace
 97 cananian 1.1.2.1                         (q, new INSTANCEOF(q.getFactory(), q, q.dst(),
 98 cananian 1.1.2.1                                            q.src(), widen(q.hclass())));
 99 cananian 1.1.2.1                 }
100 cananian 1.1.2.1                 public void visit(TYPESWITCH q) {
101 cananian 1.1.2.1                     HClass[] keys = (HClass[]) q.keys().clone();
102 cananian 1.1.2.1                     for (int i=0; i<keys.length; i++)
103 cananian 1.1.2.1                         keys[i] = widen(keys[i]);
104 cananian 1.1.2.1                     Quad.replace
105 cananian 1.1.2.1                         (q, new TYPESWITCH(q.getFactory(), q, q.index(),
106 cananian 1.1.2.1                                            keys, q.dst(), q.src(),
107 cananian 1.1.2.1                                            q.hasDefault()));
108 cananian 1.1.2.1                 }
109 cananian 1.1.2.1             };
110 cananian 1.6             for (Iterator<Quad> it=new SnapshotIterator<Quad>
111 cananian 1.6                      (hc.getElementsI()); it.hasNext(); )
112 cananian 1.6                 it.next().accept(qv);
113 cananian 1.1.2.1         // done.
114 cananian 1.1.2.1         return hc;
115 cananian 1.1.2.1     }
116 cananian 1.1.2.1     HClass widen(HClass hc) {
117 cananian 1.1.2.1         if (hc.isPrimitive() || hc.isInterface())
118 cananian 1.1.2.1             return hc;
119 cananian 1.1.2.1         if (hc.isArray())
120 cananian 1.1.2.1             return HClassUtil.arrayClass
121 cananian 1.1.2.1                 (linker, widen(HClassUtil.baseClass(hc)), HClassUtil.dims(hc));
122 cananian 1.7             List<PairList<HField,Number>> sortedFields = listmap.get(hc);
123 cananian 1.1.2.1         if (sortedFields==null) return hc; // not a split class.
124 cananian 1.7             PairList<HField,Number> lastpair =
125 cananian 1.5                 sortedFields.get(sortedFields.size()-1);
126 cananian 1.1.2.1         HField lastF = (HField) lastpair.get(0);
127 cananian 1.5             HClass broadest = field2class.get(lastF);
128 cananian 1.3.2.1         assert broadest!=null;
129 cananian 1.1.2.1         return broadest;
130 cananian 1.1.2.1     }
131 cananian 1.2     }