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      }