1 cananian 1.1.4.1 // ClassMethodMap.java, created Fri Oct  8 15:06:25 1999 by cananian
 2 cananian 1.1.4.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu>
 3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
 4 cananian 1.1.4.1 package harpoon.Backend.Analysis;
 5 cananian 1.1.4.1 
 6 cananian 1.1.4.1 import harpoon.Backend.Maps.MethodMap;
 7 cananian 1.1.4.1 import harpoon.ClassFile.HClass;
 8 cananian 1.1.4.1 import harpoon.ClassFile.HConstructor;
 9 cananian 1.1.4.1 import harpoon.ClassFile.HMethod;
10 cananian 1.1.4.1 import harpoon.Util.Util;
11 cananian 1.1.4.1 
12 cananian 1.1.4.1 import java.lang.reflect.Modifier;
13 cananian 1.1.4.1 import java.util.ArrayList;
14 cananian 1.1.4.1 import java.util.Collections;
15 cananian 1.1.4.1 import java.util.HashMap;
16 cananian 1.1.4.1 import java.util.HashSet;
17 cananian 1.1.4.1 import java.util.Iterator;
18 cananian 1.1.4.1 import java.util.List;
19 cananian 1.1.4.1 import java.util.Map;
20 cananian 1.1.4.1 import java.util.Set;
21 cananian 1.1.4.1 
22 cananian 1.1.4.1 /**
23 cananian 1.1.4.1  * A <code>ClassMethodMap</code> is a method map for virtual methods of
24 cananian 1.1.4.1  * an object (not static, not private, not constructors).  It uses the
25 cananian 1.1.4.1  * natural ordering (under <code>Comparable</code> of the methods when
26 cananian 1.1.4.1  * possible and caches results for efficiency.
27 cananian 1.1.4.1  * 
28 cananian 1.1.4.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
29 cananian 1.4      * @version $Id: ClassMethodMap.java,v 1.4 2002/04/10 03:02:22 cananian Exp $
30 cananian 1.1.4.1  */
31 cananian 1.1.4.1 public class ClassMethodMap extends MethodMap {
32 cananian 1.1.4.1     
33 cananian 1.1.4.1     /** Creates a <code>ClassMethodMap</code>. */
34 cananian 1.1.4.1     public ClassMethodMap() { /* no special initialization. */ }
35 cananian 1.1.4.1 
36 cananian 1.1.4.1     public int methodOrder(HMethod hm) {
37 cananian 1.1.4.1         // method must be a virtual class method and thus
38 cananian 1.1.4.1         // 1) not an interface method
39 cananian 1.1.4.1         // 2) not static, not private, and not a constructor.
40 cananian 1.3.2.1         assert !hm.isInterfaceMethod();
41 cananian 1.3.2.1         assert isVirtual(hm);
42 cananian 1.1.4.1         // check cache first.
43 cananian 1.1.4.1         if (cache.containsKey(hm)) return ((Integer)cache.get(hm)).intValue();
44 cananian 1.1.4.1         // we actually compute numbers for a whole class at a time.
45 cananian 1.1.4.1         HClass hc = hm.getDeclaringClass();
46 cananian 1.1.4.1         HClass sc = hc.getSuperclass();
47 cananian 1.1.4.1         HMethod[] prenumbered = (sc==null)?new HMethod[0]:sc.getMethods();
48 cananian 1.1.4.1         HMethod[] tobenumbered= hc.getMethods();
49 cananian 1.1.4.1         int prenonstatic=0, tobenonstatic=0;
50 cananian 1.1.4.1         // identify and remove methods matching signatures of methods
51 cananian 1.1.4.1         // already numbered (because they belong to the parent)
52 cananian 1.1.4.1         Map presigs = new HashMap();
53 cananian 1.1.4.1         for (int i=0; i<prenumbered.length; i++) {
54 cananian 1.1.4.1             if (!isVirtual(prenumbered[i])) continue;
55 cananian 1.1.4.1             // not static, not private, and not a constructor...
56 cananian 1.1.4.1             prenonstatic++;
57 cananian 1.1.4.1             String sig = prenumbered[i].getName() +
58 cananian 1.1.4.1                 prenumbered[i].getDescriptor();
59 cananian 1.1.4.1             presigs.put(sig, prenumbered[i]);
60 cananian 1.1.4.1         }
61 cananian 1.1.4.1         // create remainder list of class-local (not inherited) methods.
62 cananian 1.1.4.1         // (also filter out static methods)
63 cananian 1.1.4.1         List remainder = new ArrayList();
64 cananian 1.1.4.1         for (int i=0; i<tobenumbered.length; i++) {
65 cananian 1.1.4.1             if (!isVirtual(tobenumbered[i])) continue;
66 cananian 1.1.4.1             // not static, not private, and not a constructor...
67 cananian 1.1.4.1             tobenonstatic++;
68 cananian 1.1.4.1             String sig = tobenumbered[i].getName() +
69 cananian 1.1.4.1                 tobenumbered[i].getDescriptor();
70 cananian 1.1.4.1             if (!presigs.containsKey(sig))
71 cananian 1.1.4.1                 remainder.add(tobenumbered[i]);
72 cananian 1.1.4.1             else if (!cache.containsKey(tobenumbered[i]))
73 cananian 1.1.4.1                 // number inherited methods the same way they are numbered
74 cananian 1.1.4.1                 // in the parent.
75 cananian 1.1.4.1                 cache.put(tobenumbered[i],
76 cananian 1.1.4.1                           new Integer(methodOrder((HMethod)presigs.get(sig))));
77 cananian 1.1.4.1         }
78 cananian 1.1.4.1         // now sort the class-local methods
79 cananian 1.1.4.1         Collections.sort(remainder);
80 cananian 1.1.4.1         // and make a coherent numbering.
81 cananian 1.1.4.1         int num = prenonstatic;
82 cananian 1.1.4.1         for (Iterator it=remainder.iterator(); it.hasNext(); )
83 cananian 1.1.4.1             cache.put(it.next(), new Integer(num++));
84 cananian 1.3.2.1         assert num==tobenonstatic : num + "!=" + tobenonstatic;
85 cananian 1.1.4.1         // by this point the method should have a numbering in the cache.
86 cananian 1.1.4.1         return ((Integer)cache.get(hm)).intValue();
87 cananian 1.1.4.1     }
88 cananian 1.1.4.1     private final Map cache = new HashMap();
89 cananian 1.1.4.1 
90 cananian 1.1.4.1     /** Determine if a method is "virtual" -- that is, handled by this
91 cananian 1.1.4.1      *  map (and included in the class dispatch table). */
92 cananian 1.1.4.1     private static boolean isVirtual(HMethod hm) {
93 cananian 1.1.4.1         if (hm.isStatic()) return false;
94 cananian 1.1.4.1         if (Modifier.isPrivate(hm.getModifiers())) return false;
95 cananian 1.1.4.1         if (hm instanceof HConstructor) return false;
96 cananian 1.1.4.1         return true;
97 cananian 1.1.4.1     }
98 cananian 1.2     }