1 cananian 1.1.2.1 // PreOrderClazNumbering.java, created Sun Mar 10 05:24:15 2002 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.Backend.RuntimeTiny;
 5 cananian 1.1.2.1 
 6 cananian 1.1.2.1 import harpoon.Analysis.ClassHierarchy;
 7 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
 8 cananian 1.1.2.1 import harpoon.Util.HClassUtil;
 9 cananian 1.1.2.1 
10 cananian 1.1.2.1 import java.util.Collections;
11 cananian 1.1.2.1 import java.util.Comparator;
12 cananian 1.1.2.1 import java.util.HashMap;
13 cananian 1.1.2.1 import java.util.Iterator;
14 cananian 1.1.2.1 import java.util.Map;
15 cananian 1.1.2.1 import java.util.Set;
16 cananian 1.1.2.1 /**
17 cananian 1.1.2.1  * <code>PreOrderClazNumbering</code> will number single-inheritance
18 cananian 1.1.2.1  * instantiated classes (i.e. not interfaces or arrays of interfaces)
19 cananian 1.1.2.1  * such that all classes numbered in an interval [a,b] will be
20 cananian 1.1.2.1  * instances of the first common superclass of A and B, where
21 cananian 1.1.2.1  * <code>clazNumber(A)==a</code> and <code>clazNumber(B)==b</code>.
22 cananian 1.1.2.1  * This is useful for implementing quick 'instanceOf' tests;
23 cananian 1.1.2.1  * to determine if an object is an instanceof class A, you can
24 cananian 1.1.2.1  * simply see if the object falls within the interval
25 cananian 1.1.2.1  * <code>[classNumber(A),maxChildNumber(A)]</code>.
26 cananian 1.1.2.1  * 
27 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
28 cananian 1.2      * @version $Id: PreOrderClazNumbering.java,v 1.2 2002/04/10 03:03:43 cananian Exp $
29 cananian 1.1.2.1  */
30 cananian 1.1.2.1 public class PreOrderClazNumbering extends ClazNumbering {
31 cananian 1.1.2.1     private final Map<HClass,Integer> minmap = new HashMap<HClass,Integer>();
32 cananian 1.1.2.1     private final Map<HClass,Integer> maxmap = new HashMap<HClass,Integer>();
33 cananian 1.1.2.1     private final int max;
34 cananian 1.1.2.1     
35 cananian 1.1.2.1     /** Creates a <code>PreOrderClazNumbering</code>. */
36 cananian 1.1.2.1     public PreOrderClazNumbering(ClassHierarchy ch) {
37 cananian 1.1.2.1         Set<HClass> all = ch.instantiatedClasses();
38 cananian 1.1.2.1         HClass root = Collections.min(all, new Comparator<HClass>() {
39 cananian 1.1.2.1             public int compare(HClass a, HClass b) {
40 cananian 1.1.2.1                 // major sort key is inheritance.
41 cananian 1.1.2.1                 if (a.isInstanceOf(b) && !b.isInstanceOf(a)) return 1;
42 cananian 1.1.2.1                 if (b.isInstanceOf(a) && !a.isInstanceOf(b)) return -1;
43 cananian 1.1.2.1                 // break ties by sorting lexicographically.
44 cananian 1.1.2.1                 return a.getDescriptor().compareTo(b.getDescriptor());
45 cananian 1.1.2.1             }
46 cananian 1.1.2.1         });
47 cananian 1.1.2.1         assert root.getName().equals("java.lang.Object");
48 cananian 1.1.2.1         this.max = number(-1, root, ch);
49 cananian 1.1.2.1 
50 cananian 1.1.2.1     }
51 cananian 1.1.2.1     private int number(int n, HClass hc, ClassHierarchy ch) {
52 cananian 1.1.2.1         assert !(minmap.containsKey(hc) || maxmap.containsKey(hc)) :
53 cananian 1.1.2.1             "at entrance to number(), we shouldn't have a mapping for "+hc;
54 cananian 1.1.2.1         if (HClassUtil.baseClass(hc).isInterface())
55 cananian 1.1.2.1             return n; // only single-inheritance tree.
56 cananian 1.1.2.1         if (ch.instantiatedClasses().contains(hc)) n++;
57 cananian 1.1.2.1         minmap.put(hc, new Integer(n));
58 cananian 1.1.2.1         for (Iterator<HClass> it=ch.children(hc).iterator(); it.hasNext(); )
59 cananian 1.1.2.1             n=number(n, it.next(), ch);
60 cananian 1.1.2.1         maxmap.put(hc, new Integer(n));
61 cananian 1.1.2.1         assert minmap.containsKey(hc) && maxmap.containsKey(hc) :
62 cananian 1.1.2.1             "at exit to number(), we *should* have a mapping for "+hc;
63 cananian 1.1.2.1         return n;
64 cananian 1.1.2.1     }
65 cananian 1.1.2.1 
66 cananian 1.1.2.1     /** Returns the number associated with the given <code>HClass</code>. */
67 cananian 1.1.2.1     public int clazNumber(HClass hc) {
68 cananian 1.1.2.1         assert minmap.containsKey(hc) :
69 cananian 1.1.2.1             "clazNumber() not valid for the non-single-inheritance class "
70 cananian 1.1.2.1             +hc;
71 cananian 1.1.2.1         return minmap.get(hc).intValue();
72 cananian 1.1.2.1     }
73 cananian 1.1.2.1     /** Returns the maximum number associated with an instantiatable
74 cananian 1.1.2.1      *  child of the given <code>HClass</code>. */
75 cananian 1.1.2.1     public int maxChildNumber(HClass hc) {
76 cananian 1.1.2.1         assert maxmap.containsKey(hc) :
77 cananian 1.1.2.1             "maxChildNumber() not valid for the non-single-inheritance class "
78 cananian 1.1.2.1             +hc;
79 cananian 1.1.2.1         return maxmap.get(hc).intValue();
80 cananian 1.1.2.1     }
81 cananian 1.1.2.1     /** Returns the smallest number which this <code>ClazNumbering</code>
82 cananian 1.1.2.1      *  will associate with any <code>HClass</code>. */
83 cananian 1.1.2.1     public int minNumber() { return 0; }
84 cananian 1.1.2.1     /** Returns the largest number which this <code>ClazNumbering</code>
85 cananian 1.1.2.1      *  will associate with any <code>HClass</code>. */
86 cananian 1.1.2.1     public int maxNumber() { return max; }
87 cananian 1.1.2.1 
88 cananian 1.2     }