1 cananian 1.1.2.1 // Nonvirtualize.java, created Fri Oct 20 23:35:56 2000 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.Quads; 5 cananian 1.1.2.1 6 cananian 1.1.2.2 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Backend.Maps.FinalMap; 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.3 import harpoon.ClassFile.HMethod; 12 cananian 1.1.2.1 import harpoon.IR.Quads.CALL; 13 cananian 1.1.2.1 import harpoon.IR.Quads.Quad; 14 cananian 1.4 import net.cscott.jutil.SnapshotIterator; 15 cananian 1.1.2.2 16 cananian 1.3 import java.util.Iterator; 17 cananian 1.1.2.2 import java.util.Set; 18 cananian 1.1.2.1 /** 19 cananian 1.1.2.1 * <code>Nonvirtualize</code> uses a <code>FinalMap</code> to 20 cananian 1.1.2.1 * change virtual method invocations to non-virtual invocations, 21 cananian 1.1.2.1 * where this is safe. Virtual method invocation is slower 22 cananian 1.1.2.1 * than non-virtual invocation. 23 cananian 1.1.2.1 * 24 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 25 cananian 1.4 * @version $Id: Nonvirtualize.java,v 1.4 2004/02/08 01:53:14 cananian Exp $ 26 cananian 1.1.2.1 * @see harpoon.Backend.Maps.DefaultFinalMap 27 cananian 1.1.2.1 * @see harpoon.Backend.Maps.CHFinalMap 28 cananian 1.1.2.1 */ 29 cananian 1.1.2.1 public class Nonvirtualize 30 cananian 1.3 extends harpoon.Analysis.Transformation.MethodMutator<Quad> { 31 cananian 1.1.2.1 /** The <code>FinalMap</code> we will consult for our devirtualization. */ 32 cananian 1.1.2.1 private final FinalMap fm; 33 cananian 1.1.2.2 /** An optional set of callable methods to limit our devirtualization. */ 34 cananian 1.3 private final Set<HMethod> callable; 35 cananian 1.1.2.1 36 cananian 1.1.2.1 /** Creates a <code>Nonvirtualize</code> using the given 37 cananian 1.1.2.1 * <code>FinalMap</code>. 38 cananian 1.1.2.1 * @see harpoon.Backend.Maps.DefaultFinalMap 39 cananian 1.1.2.1 * @see harpoon.Backend.Maps.CHFinalMap 40 cananian 1.1.2.1 */ 41 cananian 1.1.2.1 public Nonvirtualize(HCodeFactory hcf, FinalMap fm) { 42 cananian 1.1.2.2 this(hcf, fm, null); 43 cananian 1.1.2.2 } 44 cananian 1.1.2.2 /** Creates a <code>Nonvirtualize</code> using the given 45 cananian 1.1.2.2 * <code>FinalMap</code>; the given <code>ClassHierarchy</code> 46 cananian 1.1.2.2 * is used to avoid devirtualizing calls to uncallable methods 47 cananian 1.1.2.2 * (which artificially inflates the class hierarchy size). 48 cananian 1.1.2.2 * @see harpoon.Backend.Maps.DefaultFinalMap 49 cananian 1.1.2.2 * @see harpoon.Backend.Maps.CHFinalMap 50 cananian 1.1.2.2 */ 51 cananian 1.1.2.2 public Nonvirtualize(HCodeFactory hcf, FinalMap fm, ClassHierarchy ch) { 52 cananian 1.1.2.1 super(hcf); 53 cananian 1.1.2.1 this.fm = fm; 54 cananian 1.1.2.2 this.callable = (ch==null) ? null : ch.callableMethods(); 55 cananian 1.1.2.1 } 56 cananian 1.1.2.1 57 cananian 1.3 protected HCode<Quad> mutateHCode(HCodeAndMaps<Quad> input) { 58 cananian 1.3 HCode<Quad> hc = input.hcode(); 59 cananian 1.3 for (Iterator<Quad> it = new SnapshotIterator<Quad>(hc.getElementsI()); 60 cananian 1.3 it.hasNext(); ) { 61 cananian 1.3 Quad aquad = it.next(); 62 cananian 1.3 if (!(aquad instanceof CALL)) continue; 63 cananian 1.3 CALL q = (CALL) aquad; 64 cananian 1.1.2.1 if (!q.isVirtual()) continue; 65 cananian 1.1.2.1 if (!fm.isFinal(q.method())) continue; 66 cananian 1.1.2.2 // don't devirtualize uncallable methods, as the static reference 67 cananian 1.1.2.2 // will make it seem like they are callable. 68 cananian 1.1.2.2 if (callable!=null && !callable.contains(q.method())) continue; 69 cananian 1.1.2.1 // okay, this is a CALL to a final method. make it non-virtual! 70 cananian 1.1.2.1 CALL nq = new CALL(q.getFactory(), q, q.method(), q.params(), 71 cananian 1.1.2.1 q.retval(), q.retex(), false/*isVirtual*/, 72 cananian 1.1.2.1 q.isTailCall(), q.dst(), q.src()); 73 cananian 1.1.2.1 Quad.replace(q, nq); 74 cananian 1.1.2.1 Quad.transferHandlers(q, nq); 75 cananian 1.1.2.1 // ta-da! 76 cananian 1.1.2.1 } 77 cananian 1.1.2.1 return hc; 78 cananian 1.1.2.1 } 79 cananian 1.2 }