1 cananian 1.1.2.1 // CHFinalMap.java, created Fri Oct 20 23:09:43 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.Backend.Maps;
 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.ClassFile.HConstructor;
 9 cananian 1.1.2.1 import harpoon.ClassFile.HField;
10 cananian 1.1.2.1 import harpoon.ClassFile.HMethod;
11 cananian 1.3     import net.cscott.jutil.WorkSet;
12 cananian 1.1.2.1 
13 cananian 1.1.2.1 import java.lang.reflect.Modifier;
14 cananian 1.1.2.1 import java.util.HashMap;
15 cananian 1.1.2.1 import java.util.Map;
16 cananian 1.1.2.1 /**
17 cananian 1.1.2.1  * <code>CHFinalMap</code> is a slightly smarter <code>FinalMap</code>
18 cananian 1.1.2.1  * that, given a <code>ClassHierarchy</code> for context, aggressively
19 cananian 1.1.2.1  * makes methods final if the <code>ClassHierarchy</code> doesn't contain
20 cananian 1.1.2.1  * a reachable method which overrides it.
21 cananian 1.1.2.1  * 
22 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
23 cananian 1.3      * @version $Id: CHFinalMap.java,v 1.3 2004/02/08 01:57:37 cananian Exp $
24 cananian 1.1.2.1  */
25 cananian 1.1.2.4 public class CHFinalMap extends DefaultFinalMap
26 cananian 1.1.2.4     implements java.io.Serializable {
27 cananian 1.1.2.1     private final ClassHierarchy ch;
28 cananian 1.1.2.1     
29 cananian 1.1.2.1     /** Creates a <code>CHFinalMap</code>. */
30 cananian 1.1.2.1     public CHFinalMap(ClassHierarchy ch) { this.ch = ch; }
31 cananian 1.1.2.1 
32 cananian 1.1.2.1     public boolean isFinal(HClass hc) {
33 cananian 1.1.2.1         return super.isFinal(hc) || ch.children(hc).size()==0;
34 cananian 1.1.2.1     }
35 cananian 1.1.2.1     public boolean isFinal(HMethod hm) {
36 cananian 1.1.2.3         // abstract methods are never final, even if no reachable methods
37 cananian 1.1.2.3         // implement it. (this deals with unexecutable method calls)
38 cananian 1.1.2.3         if (Modifier.isAbstract(hm.getModifiers())) return false;
39 cananian 1.1.2.3         // at least as precise as DefaultFinalMap
40 cananian 1.1.2.1         if (super.isFinal(hm)) return true;
41 cananian 1.1.2.1         // call non-virtual methods final.
42 cananian 1.1.2.1         if (hm.isStatic() ||
43 cananian 1.1.2.1             Modifier.isPrivate(hm.getModifiers()) ||
44 cananian 1.1.2.1             hm instanceof HConstructor) return true;
45 cananian 1.1.2.1         // next bit is time consuming.  check cache first.
46 cananian 1.1.2.4         if (cache==null) cache = new HashMap();
47 cananian 1.1.2.2         if (!cache.containsKey(hm)) {
48 cananian 1.1.2.2             // if no overrides, this is final.
49 cananian 1.1.2.2             cache.put(hm, new Boolean(ch.overrides(hm).size()==0));
50 cananian 1.1.2.1         }
51 cananian 1.1.2.2         return ((Boolean) cache.get(hm)).booleanValue();
52 cananian 1.1.2.1     }
53 cananian 1.1.2.4     private transient Map cache = null;
54 cananian 1.2     }