1 marinov 1.1.2.1 // InterProc.java, created Fri Nov 20 19:21:40 1998 by marinov 2 cananian 1.1.2.8 // Copyright (C) 1998 Darko Marinov <marinov@lcs.mit.edu> 3 cananian 1.1.2.8 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 marinov 1.1.2.1 package harpoon.Analysis.TypeInference; 5 marinov 1.1.2.1 6 cananian 1.1.2.13 import harpoon.IR.Quads.CALL; 7 cananian 1.1.2.13 import harpoon.Temp.Temp; 8 marinov 1.1.2.1 import java.util.Hashtable; 9 marinov 1.1.2.1 import java.util.Enumeration; 10 marinov 1.1.2.1 import harpoon.Util.Worklist; 11 cananian 1.1.2.13 import harpoon.ClassFile.HClass; 12 cananian 1.1.2.13 import harpoon.ClassFile.HCode; 13 cananian 1.1.2.13 import harpoon.ClassFile.HCodeFactory; 14 cananian 1.1.2.13 import harpoon.ClassFile.HField; 15 cananian 1.1.2.13 import harpoon.ClassFile.HMethod; 16 cananian 1.1.2.13 import harpoon.ClassFile.Linker; 17 cananian 1.1.2.10 import harpoon.Analysis.ClassHierarchy; 18 cananian 1.1.2.11 import harpoon.Analysis.Quads.QuadClassHierarchy; 19 cananian 1.1.2.12 20 cananian 1.1.2.12 import java.util.Collections; 21 marinov 1.1.2.1 /** 22 marinov 1.1.2.1 * <code>InterProc</code> 23 marinov 1.1.2.1 * 24 marinov 1.1.2.1 * @author Darko Marinov <marinov@lcs.mit.edu> 25 cananian 1.3 * @version $Id: InterProc.java,v 1.3 2004/02/08 01:54:33 cananian Exp $ 26 marinov 1.1.2.1 */ 27 marinov 1.1.2.1 28 marinov 1.1.2.1 public class InterProc implements harpoon.Analysis.Maps.SetTypeMap { 29 marinov 1.1.2.1 HCode main; 30 marinov 1.1.2.1 boolean analyzed = false; 31 marinov 1.1.2.1 Hashtable proc = new Hashtable(); 32 marinov 1.1.2.1 ClassHierarchy ch = null; 33 cananian 1.1.2.7 HCodeFactory hcf; 34 cananian 1.1.2.12 Linker linker; 35 marinov 1.1.2.1 36 marinov 1.1.2.1 /** Creates an <code>InterProc</code> analyzer. */ 37 cananian 1.1.2.7 public InterProc(HCode main, HCodeFactory hcf) { 38 cananian 1.1.2.7 this.main = main; this.hcf = hcf; 39 cananian 1.1.2.12 this.linker = main.getMethod().getDeclaringClass().getLinker(); 40 cananian 1.1.2.7 } 41 cananian 1.1.2.7 public InterProc(HCode main, ClassHierarchy ch, HCodeFactory hcf) { 42 cananian 1.1.2.7 this.main = main; this.ch = ch; this.hcf = hcf; 43 cananian 1.1.2.12 this.linker = main.getMethod().getDeclaringClass().getLinker(); 44 cananian 1.1.2.7 } 45 marinov 1.1.2.1 46 marinov 1.1.2.1 public SetHClass setTypeMap(HCode c, Temp t) { 47 marinov 1.1.2.1 analyze(); 48 marinov 1.1.2.3 IntraProc i = (IntraProc) proc.get(c.getMethod()); 49 marinov 1.1.2.3 if (i==null) 50 marinov 1.1.2.3 return i.getTempType(t); 51 marinov 1.1.2.3 else 52 marinov 1.1.2.3 return new SetHClass(); 53 marinov 1.1.2.1 } 54 marinov 1.1.2.1 55 marinov 1.1.2.1 public SetHClass getReturnType(HCode c) { 56 marinov 1.1.2.1 analyze(); 57 marinov 1.1.2.3 IntraProc i = (IntraProc) proc.get(c.getMethod()); 58 marinov 1.1.2.3 if (i==null) 59 marinov 1.1.2.3 return i.getReturnType(); 60 marinov 1.1.2.3 else 61 marinov 1.1.2.3 return new SetHClass(); 62 marinov 1.1.2.1 } 63 marinov 1.1.2.1 64 marinov 1.1.2.1 public HMethod[] calls(HMethod m) { 65 marinov 1.1.2.1 analyze(); 66 marinov 1.1.2.1 return ((IntraProc)proc.get(m)).calls(); 67 marinov 1.1.2.1 } 68 marinov 1.1.2.6 public HMethod[] calls(HMethod m, CALL cs, boolean last) { 69 marinov 1.1.2.4 analyze(); 70 marinov 1.1.2.6 return ((IntraProc)proc.get(m)).calls(cs, last); 71 marinov 1.1.2.4 } 72 marinov 1.1.2.1 73 marinov 1.1.2.5 AuxUniqueFIFO wl; 74 marinov 1.1.2.4 public void analyze() { 75 marinov 1.1.2.1 if (analyzed) return; else analyzed = true; 76 marinov 1.1.2.1 /* main method, the one from which the analysis starts. */ 77 marinov 1.1.2.1 HMethod m = main.getMethod(); 78 marinov 1.1.2.1 /* build class hierarchy of classess reachable from main. 79 marinov 1.1.2.1 used for coning, i.e. finding all children of a given class. */ 80 cananian 1.1.2.12 if (ch==null) ch = new QuadClassHierarchy(linker, Collections.singleton(m), hcf); 81 marinov 1.1.2.1 cc = new ClassCone(ch); 82 marinov 1.1.2.1 /* worklist of methods that are to be processed. */ 83 marinov 1.1.2.6 wl = new AuxUniqueFIFO(16); 84 marinov 1.1.2.3 /* put class initializers for reachable classes on the worklist. */ 85 marinov 1.1.2.1 SetHClass[] ep = new SetHClass[0]; 86 marinov 1.1.2.1 for (Enumeration e = classInitializers(ch); e.hasMoreElements(); ) { 87 marinov 1.1.2.1 HMethod ci = (HMethod)e.nextElement(); 88 marinov 1.1.2.1 getIntra(null, ci, ep); 89 marinov 1.1.2.1 } 90 marinov 1.1.2.3 /* ugly hack - add method(s) invoked automatically at jvm start-up??? */ 91 cananian 1.1.2.12 HMethod ci = linker.forName("java.lang.System").getMethod("initializeSystemClass", new HClass[0]); 92 marinov 1.1.2.3 getIntra(null, ci, ep); 93 marinov 1.1.2.1 /* put the main method on the worklist. */ 94 marinov 1.1.2.1 HClass[] c = m.getParameterTypes(); 95 marinov 1.1.2.1 SetHClass[] p = new SetHClass[c.length]; 96 marinov 1.1.2.1 for (int i=0; i<c.length; i++) 97 marinov 1.1.2.1 p[i] = cone(c[i]); 98 marinov 1.1.2.1 getIntra(null, m, p); 99 marinov 1.1.2.1 /* use straightforward worklist algorithm. */ 100 marinov 1.1.2.1 while (!wl.isEmpty()) { 101 marinov 1.1.2.1 IntraProc i = (IntraProc)wl.pull(); 102 marinov 1.1.2.1 i.analyze(); 103 marinov 1.1.2.1 } 104 marinov 1.1.2.1 } 105 marinov 1.1.2.1 106 marinov 1.1.2.1 ClassCone cc; 107 marinov 1.1.2.1 SetHClass cone(HClass c) { return cc.cone(c); } 108 marinov 1.1.2.1 109 marinov 1.1.2.5 void reanalyze(IntraProc i) { wl.push(i, i.depth); } 110 marinov 1.1.2.1 111 marinov 1.1.2.1 IntraProc getIntra(IntraProc c, HMethod m, SetHClass[] p) { 112 marinov 1.1.2.1 IntraProc i = (IntraProc)proc.get(m); 113 marinov 1.1.2.1 if (i==null) { 114 cananian 1.1.2.7 i = new IntraProc(this, m, hcf); 115 marinov 1.1.2.1 proc.put(m, i); 116 marinov 1.1.2.1 i.addParameters(p); 117 marinov 1.1.2.5 if (c!=null) i.addCallee(c); 118 marinov 1.1.2.1 reanalyze(i); 119 marinov 1.1.2.5 } else if (i.addParameters(p)) { 120 marinov 1.1.2.5 if (c!=null) i.addCallee(c); 121 marinov 1.1.2.5 reanalyze(i); 122 marinov 1.1.2.5 } 123 marinov 1.1.2.1 return i; 124 marinov 1.1.2.1 } 125 marinov 1.1.2.1 126 marinov 1.1.2.1 Hashtable instVar = new Hashtable(); 127 marinov 1.1.2.1 SetHClass getType(HField f, IntraProc i) { 128 marinov 1.1.2.1 FieldType t = (FieldType)instVar.get(f); 129 marinov 1.1.2.1 if (t==null) { 130 marinov 1.1.2.1 t = new FieldType(); 131 marinov 1.1.2.1 instVar.put(f, t); 132 marinov 1.1.2.1 } 133 marinov 1.1.2.1 t.addCallee(i); 134 marinov 1.1.2.1 return t.getType(); 135 marinov 1.1.2.4 } 136 marinov 1.1.2.1 void mergeType(HField f, SetHClass s) { 137 marinov 1.1.2.1 FieldType t = (FieldType)instVar.get(f); 138 marinov 1.1.2.1 if (t==null) { 139 marinov 1.1.2.1 t = new FieldType(); 140 marinov 1.1.2.1 instVar.put(f, t); 141 marinov 1.1.2.1 } 142 marinov 1.1.2.1 if (t.union(s)) 143 marinov 1.1.2.1 for (Enumeration e=t.getCallees(); e.hasMoreElements(); ) 144 marinov 1.1.2.1 reanalyze((IntraProc)e.nextElement()); 145 marinov 1.1.2.1 } 146 marinov 1.1.2.1 147 marinov 1.1.2.1 Enumeration classInitializers(final ClassHierarchy ch) { 148 marinov 1.1.2.1 return new Enumeration() { 149 cananian 1.1.2.9 Enumeration e = 150 cananian 1.3 new net.cscott.jutil.IteratorEnumerator(ch.classes().iterator()); 151 marinov 1.1.2.1 HMethod m = null; 152 marinov 1.1.2.1 private void advance() { 153 marinov 1.1.2.1 while (e.hasMoreElements()&&(m==null)) { 154 marinov 1.1.2.1 HClass c = (HClass)e.nextElement(); 155 marinov 1.1.2.1 m = c.getClassInitializer(); 156 marinov 1.1.2.1 } 157 marinov 1.1.2.1 } 158 marinov 1.1.2.1 public boolean hasMoreElements() { advance(); return (m!=null); } 159 marinov 1.1.2.1 public Object nextElement() { 160 marinov 1.1.2.1 advance(); 161 marinov 1.1.2.1 if (m!=null) { HMethod n = m; m = null; return n; } 162 marinov 1.1.2.1 else return null; 163 marinov 1.1.2.1 } 164 marinov 1.1.2.1 }; 165 marinov 1.1.2.1 } 166 marinov 1.1.2.1 167 cananian 1.2 }