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     }