1 kkz      1.1.2.1  // AsyncCode.java, created Thu Nov 11 15:17:54 1999 by kkz
  2 cananian 1.1.2.68 // Copyright (C) 1999 Karen K. Zee <kkz@alum.mit.edu>
  3 bdemsky  1.1.2.8  //                    and Brian Demsky <bdemsky@mit.edu>
  4 kkz      1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  5 kkz      1.1.2.1  package harpoon.Analysis.EventDriven;
  6 kkz      1.1.2.1  
  7 bdemsky  1.1.2.8  import harpoon.Analysis.ContBuilder.ContBuilder;
  8 bdemsky  1.1.2.8  import harpoon.Analysis.EnvBuilder.EnvBuilder;
  9 bdemsky  1.1.2.8  import harpoon.Analysis.Quads.QuadLiveness;
 10 bdemsky  1.1.2.34 import harpoon.Analysis.ClassHierarchy;
 11 bdemsky  1.1.2.28 import harpoon.Analysis.Maps.TypeMap;
 12 bdemsky  1.1.2.54 import harpoon.Analysis.AllCallers;
 13 cananian 1.1.2.38 import harpoon.ClassFile.CachingCodeFactory;
 14 kkz      1.1.2.1  import harpoon.ClassFile.HClass;
 15 bdemsky  1.1.2.25 import harpoon.ClassFile.HClassMutator;
 16 bdemsky  1.1.2.25 import harpoon.ClassFile.HMethod;
 17 bdemsky  1.1.2.25 import harpoon.ClassFile.HMethodMutator;
 18 kkz      1.1.2.1  import harpoon.ClassFile.HCode;
 19 kkz      1.1.2.1  import harpoon.ClassFile.HConstructor;
 20 bdemsky  1.1.2.8  import harpoon.ClassFile.HField;
 21 bdemsky  1.1.2.25 import harpoon.ClassFile.Loader;
 22 bdemsky  1.1.2.25 import harpoon.ClassFile.Linker;
 23 bdemsky  1.1.2.25 import harpoon.ClassFile.UniqueName;
 24 bdemsky  1.1.2.25 
 25 cananian 1.1.2.67 import harpoon.IR.Quads.CALL;
 26 cananian 1.1.2.67 import harpoon.IR.Quads.Code;
 27 cananian 1.1.2.67 import harpoon.IR.Quads.Edge;
 28 cananian 1.1.2.67 import harpoon.IR.Quads.FOOTER;
 29 cananian 1.1.2.67 import harpoon.IR.Quads.GET;
 30 cananian 1.1.2.67 import harpoon.IR.Quads.HEADER;
 31 cananian 1.1.2.67 import harpoon.IR.Quads.METHOD;
 32 cananian 1.1.2.67 import harpoon.IR.Quads.Quad;
 33 cananian 1.1.2.67 import harpoon.IR.Quads.QuadFactory;
 34 cananian 1.1.2.67 import harpoon.IR.Quads.QuadSSI;
 35 cananian 1.1.2.67 import harpoon.IR.Quads.QuadVisitor;
 36 cananian 1.1.2.67 import harpoon.IR.Quads.RETURN;
 37 cananian 1.1.2.67 import harpoon.IR.Quads.SET;
 38 cananian 1.1.2.67 import harpoon.IR.Quads.THROW;
 39 kkz      1.1.2.1  import harpoon.Temp.Temp;
 40 kkz      1.1.2.1  import harpoon.Temp.TempFactory;
 41 bdemsky  1.1.2.8  import harpoon.Temp.CloningTempMap;
 42 kkz      1.1.2.2  import harpoon.Util.Util;
 43 cananian 1.6      import net.cscott.jutil.WorkSet;
 44 kkz      1.1.2.1  
 45 bdemsky  1.1.2.8  import java.util.HashMap;
 46 kkz      1.1.2.1  import java.util.Iterator;
 47 kkz      1.1.2.1  import java.util.Map;
 48 kkz      1.1.2.1  import java.util.Set;
 49 bdemsky  1.1.2.49 import java.lang.reflect.Modifier;
 50 bdemsky  1.1.2.8  
 51 kkz      1.1.2.1  /**
 52 kkz      1.1.2.1   * <code>AsyncCode</code>
 53 kkz      1.1.2.1   * 
 54 cananian 1.1.2.68  * @author Karen K. Zee <kkz@alum.mit.edu>
 55 cananian 1.6       * @version $Id: AsyncCode.java,v 1.6 2004/02/08 01:51:58 cananian Exp $
 56 kkz      1.1.2.1   */
 57 bdemsky  1.1.2.8  public class AsyncCode {
 58 kkz      1.1.2.1  
 59 bdemsky  1.1.2.8      /** Creates a <code>AsyncCode</code>. 
 60 bdemsky  1.1.2.8       *
 61 bdemsky  1.1.2.8       *  @param hc
 62 bdemsky  1.1.2.8       *         the <code>HCode</code> from which to build this
 63 bdemsky  1.1.2.8       *         <code>AsyncCode</code>.
 64 bdemsky  1.1.2.15      *  @param old2new
 65 bdemsky  1.1.2.15      *         the <code>Map</code> mapping blocking methods to the
 66 bdemsky  1.1.2.15      *         new Asynchronous version
 67 bdemsky  1.1.2.15      *  @param async_todo
 68 bdemsky  1.1.2.20      *         the <code>Set</code> of old HCodes for methods to build HCodes 
 69 bdemsky  1.1.2.20      *         for the asynchronous versions
 70 bdemsky  1.1.2.8       *  @param liveness
 71 bdemsky  1.1.2.8       *         results of liveness analysis
 72 bdemsky  1.1.2.15      *  @param blockingcalls
 73 bdemsky  1.1.2.15      *         set of methods that block
 74 bdemsky  1.1.2.8       *  @param ucf
 75 cananian 1.1.2.38      *         <code>CachingCodeFactory</code> with which to register new
 76 bdemsky  1.1.2.8       *         <code>HCode</code>
 77 bdemsky  1.1.2.15      *  @param bm
 78 bdemsky  1.1.2.15      *         <code>ToAsync.BlockingMethods</code> object which tells
 79 bdemsky  1.1.2.15      *         the analysis information about lowest level blocking calls
 80 bdemsky  1.1.2.8       */
 81 kkz      1.1.2.1  
 82 bdemsky  1.1.2.8      public static void buildCode(HCode hc, Map old2new, Set async_todo, 
 83 bdemsky  1.1.2.8                             QuadLiveness liveness,
 84 bdemsky  1.1.2.8                             Set blockingcalls, 
 85 bdemsky  1.1.2.54                            CachingCodeFactory ucf, AllCallers.MethodSet bm,
 86 bdemsky  1.1.2.42                            HMethod mroot, Linker linker, ClassHierarchy ch,
 87 bdemsky  1.1.2.52                            Set other, Set done_other, boolean methodstatus,
 88 bdemsky  1.1.2.56                            TypeMap typemap, boolean optimistic,
 89 bdemsky  1.1.2.57                            boolean recycle, Set classes) 
 90 bdemsky  1.1.2.8          throws NoClassDefFoundError
 91 bdemsky  1.1.2.8      {
 92 bdemsky  1.1.2.8          System.out.println("Entering AsyncCode.buildCode()");
 93 kkz      1.1.2.1  
 94 bdemsky  1.1.2.8          Quad root = (Quad)hc.getRootElement();
 95 kkz      1.1.2.1  
 96 bdemsky  1.1.2.15         //Cont_todo is the set of quads we need to build continuations for
 97 bdemsky  1.1.2.15 
 98 bdemsky  1.1.2.8          WorkSet cont_todo=new WorkSet();
 99 bdemsky  1.1.2.8          cont_todo.add(root);
100 bdemsky  1.1.2.8  
101 bdemsky  1.1.2.8          //contmap maps blocking calls->continuations
102 bdemsky  1.1.2.15         //envmap maps blocking calls->environment class
103 bdemsky  1.1.2.8          HashMap cont_map=new HashMap();
104 bdemsky  1.1.2.8          HashMap env_map=new HashMap();
105 bdemsky  1.1.2.8          
106 bdemsky  1.1.2.15         //iterate through all of the necessary continuations for this HMethod
107 bdemsky  1.1.2.8          while(!cont_todo.isEmpty()) {
108 bdemsky  1.1.2.8              Quad quadc=(Quad) cont_todo.pop();
109 bdemsky  1.1.2.13             System.out.println("AsyncCode building continuation for "+quadc);
110 bdemsky  1.1.2.8              ContVisitor cv=new ContVisitor(cont_todo, async_todo, 
111 bdemsky  1.1.2.8                                             old2new, cont_map, 
112 bdemsky  1.1.2.8                                             env_map, liveness,
113 bdemsky  1.1.2.8                                             blockingcalls, hc.getMethod(), 
114 bdemsky  1.1.2.42                                            hc, ucf,bm,mroot, linker,ch,
115 bdemsky  1.1.2.52                                            other, done_other,methodstatus,
116 bdemsky  1.1.2.57                                            typemap,optimistic,recycle,classes);
117 bdemsky  1.1.2.8              quadc.accept(cv);
118 bdemsky  1.1.2.8          }
119 kkz      1.1.2.1      }
120 kkz      1.1.2.1  
121 bdemsky  1.1.2.8      static class ContVisitor extends QuadVisitor {
122 bdemsky  1.1.2.8          WorkSet cont_todo;
123 bdemsky  1.1.2.8          Map old2new, cont_map, env_map;
124 bdemsky  1.1.2.8          Set blockingcalls, async_todo;
125 bdemsky  1.1.2.8          HMethod hmethod;
126 bdemsky  1.1.2.8          boolean header;
127 bdemsky  1.1.2.8          CloningVisitor clonevisit;
128 bdemsky  1.1.2.8          QuadLiveness liveness;
129 cananian 1.1.2.38         CachingCodeFactory ucf;
130 bdemsky  1.1.2.25         Linker linker;
131 bdemsky  1.1.2.42         boolean methodstatus;
132 bdemsky  1.1.2.60         
133 bdemsky  1.1.2.8          public ContVisitor(WorkSet cont_todo, Set async_todo, 
134 bdemsky  1.1.2.8                             Map old2new, Map cont_map, 
135 bdemsky  1.1.2.8                             Map env_map, QuadLiveness liveness,
136 bdemsky  1.1.2.8                             Set blockingcalls, HMethod hmethod, 
137 cananian 1.1.2.38                            HCode hc, CachingCodeFactory ucf,
138 bdemsky  1.1.2.54                            AllCallers.MethodSet bm, HMethod mroot, 
139 bdemsky  1.1.2.42                            Linker linker, ClassHierarchy ch,
140 bdemsky  1.1.2.52                            Set other, Set done_other, boolean methodstatus,
141 bdemsky  1.1.2.56                            TypeMap typemap, boolean optimistic,
142 bdemsky  1.1.2.57                            boolean recycle, Set classes) {
143 bdemsky  1.1.2.8              this.liveness=liveness;
144 bdemsky  1.1.2.8              this.env_map=env_map;
145 bdemsky  1.1.2.8              this.cont_todo=cont_todo;
146 bdemsky  1.1.2.8              this.async_todo=async_todo;
147 bdemsky  1.1.2.8              this.old2new=old2new;
148 bdemsky  1.1.2.8              this.cont_map=cont_map;
149 bdemsky  1.1.2.8              this.blockingcalls=blockingcalls;
150 bdemsky  1.1.2.8              this.hmethod=hmethod;
151 bdemsky  1.1.2.8              this.header=false;
152 bdemsky  1.1.2.8              this.ucf=ucf;
153 bdemsky  1.1.2.25             this.linker=linker;
154 bdemsky  1.1.2.42             this.methodstatus=methodstatus;
155 bdemsky  1.1.2.8              this.clonevisit=new CloningVisitor(blockingcalls, cont_todo,
156 bdemsky  1.1.2.8                                                 cont_map, env_map, liveness,
157 bdemsky  1.1.2.8                                                 async_todo, old2new,
158 bdemsky  1.1.2.42                                                hc,ucf,bm,mroot, linker,ch,
159 bdemsky  1.1.2.52                                                other, done_other,methodstatus,
160 bdemsky  1.1.2.57                                                typemap,optimistic,recycle,
161 bdemsky  1.1.2.57                                                classes);
162 bdemsky  1.1.2.8          }
163 kkz      1.1.2.1  
164 bdemsky  1.1.2.53         void addCode(HMethod hm, HCode hc) {
165 bdemsky  1.1.2.53             if (clonevisit.needsRepair()) {
166 bdemsky  1.1.2.63                 hc.print(new java.io.PrintWriter(System.out, true));
167 bdemsky  1.1.2.53                 ucf.put(hm,hc);
168 bdemsky  1.1.2.54             } else {
169 bdemsky  1.1.2.54                 //hc.print(new java.io.PrintWriter(System.out, true));
170 bdemsky  1.1.2.54                 ContCodeNoSSA hco=new ContCodeNoSSA((QuadSSI)hc);
171 bdemsky  1.1.2.54                 //hco.print(new java.io.PrintWriter(System.out, true));
172 bdemsky  1.1.2.54                 HCode hcn=new ContCodeSSI(hco);
173 bdemsky  1.1.2.63                 hcn.print(new java.io.PrintWriter(System.out, true));
174 bdemsky  1.1.2.54                 ucf.put(hm,hcn);
175 bdemsky  1.1.2.54 
176 bdemsky  1.1.2.54             }
177 bdemsky  1.1.2.53         }
178 bdemsky  1.1.2.53 
179 bdemsky  1.1.2.8          public void visit(Quad q) {
180 bdemsky  1.1.2.8              System.out.println("ERROR: "+q+" in ContVisitory!!!");
181 bdemsky  1.1.2.8          }
182 bdemsky  1.1.2.8  
183 bdemsky  1.1.2.8          public void visit(HEADER q) {
184 bdemsky  1.1.2.15             //Handles building HCode's for the HEADER quad...
185 bdemsky  1.1.2.8              //need to build continuation for this Header...
186 bdemsky  1.1.2.8              //nmh is the HMethod we wish to attach this HCode to
187 bdemsky  1.1.2.42             HMethod nhm=methodstatus?hmethod:(HMethod)old2new.get(hmethod);
188 bdemsky  1.1.2.8              //mark header flag
189 bdemsky  1.1.2.13             System.out.println("ContVisiting"+ q);
190 bdemsky  1.1.2.8              header=true;
191 bdemsky  1.1.2.56             clonevisit.reset(nhm,q.getFactory().tempFactory(),false,null);
192 bdemsky  1.1.2.54 
193 bdemsky  1.1.2.54 
194 bdemsky  1.1.2.13             System.out.println("Reset clone visitor");
195 bdemsky  1.1.2.8              copy(q,-1);
196 bdemsky  1.1.2.13             System.out.println("Finished copying");
197 bdemsky  1.1.2.53             addCode(nhm, clonevisit.getCode());
198 bdemsky  1.1.2.54 
199 bdemsky  1.1.2.54 
200 bdemsky  1.1.2.54 
201 bdemsky  1.1.2.8          }
202 bdemsky  1.1.2.8  
203 bdemsky  1.1.2.8          public void visit(CALL q) {
204 bdemsky  1.1.2.15             //builds continuation for CALLs
205 bdemsky  1.1.2.8              //nmh is the HMethod we wish to attach this HCode to
206 bdemsky  1.1.2.13             System.out.println("ContVisiting"+ q);
207 bdemsky  1.1.2.8              HClass hclass=(HClass) cont_map.get(q);
208 bdemsky  1.1.2.25             HClass throwable=linker.forName("java.lang.Throwable");
209 bdemsky  1.1.2.18             HMethod resume=(q.method().getReturnType()==HClass.Void)?
210 bdemsky  1.1.2.18                 hclass.getDeclaredMethod("resume",new HClass[0])
211 bdemsky  1.1.2.18                 :hclass.getDeclaredMethod("resume",
212 bdemsky  1.1.2.29                                          new HClass[] {q.method().getReturnType().isPrimitive()?q.method().getReturnType():linker.forName("java.lang.Object")});
213 bdemsky  1.1.2.8              HMethod exception=
214 bdemsky  1.1.2.8                  hclass.getDeclaredMethod("exception",
215 bdemsky  1.1.2.8                                           new HClass[] {throwable});
216 bdemsky  1.1.2.8  
217 bdemsky  1.1.2.8              //Resume method
218 bdemsky  1.1.2.15             //have to reset state in visitor class
219 bdemsky  1.1.2.56             clonevisit.reset(resume,q.getFactory().tempFactory(), true,q);
220 bdemsky  1.1.2.8              copy(q,0);
221 bdemsky  1.1.2.13             System.out.println("Finished resume copying");
222 bdemsky  1.1.2.8              //addEdges should add appropriate headers
223 bdemsky  1.1.2.53             addCode(resume, clonevisit.getCode());
224 bdemsky  1.1.2.54 
225 bdemsky  1.1.2.54 
226 bdemsky  1.1.2.54 
227 bdemsky  1.1.2.54 
228 bdemsky  1.1.2.8              //Exception method
229 bdemsky  1.1.2.56             clonevisit.reset(exception, q.getFactory().tempFactory(), true,q);
230 bdemsky  1.1.2.8              copy(q,1);
231 bdemsky  1.1.2.13             System.out.println("Finished exception copying");
232 bdemsky  1.1.2.8              //addEdges should add appropriate headers
233 bdemsky  1.1.2.53             addCode(exception, clonevisit.getCode());
234 bdemsky  1.1.2.54 
235 bdemsky  1.1.2.54 
236 bdemsky  1.1.2.8          }
237 bdemsky  1.1.2.8  
238 bdemsky  1.1.2.15         //copies the necessary quads from the original HCode
239 bdemsky  1.1.2.8          public void copy(Quad q, int resumeexception) {
240 bdemsky  1.1.2.8              //-1 normal
241 bdemsky  1.1.2.8              //0 resume
242 bdemsky  1.1.2.8              //1 exception
243 bdemsky  1.1.2.8              WorkSet todo=new WorkSet();
244 bdemsky  1.1.2.8              WorkSet done=new WorkSet();
245 bdemsky  1.1.2.15             WorkSet dontfollow=new WorkSet();
246 bdemsky  1.1.2.15 
247 bdemsky  1.1.2.14             if (resumeexception==-1) {
248 bdemsky  1.1.2.14                 //Don't want to visit the footer
249 bdemsky  1.1.2.14                 done.add(q.next(0));
250 bdemsky  1.1.2.8                  todo.push(q);
251 bdemsky  1.1.2.14             }
252 bdemsky  1.1.2.8              else
253 bdemsky  1.1.2.8                  todo.push(q.next(resumeexception));
254 bdemsky  1.1.2.8              while (!todo.isEmpty()) {
255 bdemsky  1.1.2.8                  Quad nq=(Quad) todo.pop();
256 bdemsky  1.1.2.8                  done.add(nq);
257 bdemsky  1.1.2.8                  nq.accept(clonevisit);
258 bdemsky  1.1.2.8                  if (clonevisit.follow()) {
259 bdemsky  1.1.2.8                      Quad[] next=nq.next();
260 bdemsky  1.1.2.8                      for (int i=0; i<next.length;i++)
261 bdemsky  1.1.2.8                          if (!done.contains(next[i]))
262 bdemsky  1.1.2.13                             todo.push(next[i]);
263 bdemsky  1.1.2.15                 } else
264 bdemsky  1.1.2.15                     dontfollow.add(nq);
265 kkz      1.1.2.1              }
266 bdemsky  1.1.2.13             System.out.println("Start addEdges");
267 bdemsky  1.1.2.15             clonevisit.addEdges(q,resumeexception,dontfollow);
268 bdemsky  1.1.2.13             System.out.println("Finished addEdges");
269 bdemsky  1.1.2.8          }
270 bdemsky  1.1.2.8  
271 bdemsky  1.1.2.8          public boolean isHeader() {
272 bdemsky  1.1.2.8              return header;
273 bdemsky  1.1.2.8          }
274 bdemsky  1.1.2.8      }
275 bdemsky  1.1.2.8  
276 bdemsky  1.1.2.26     static class ChangingVisitor extends QuadVisitor {
277 bdemsky  1.1.2.26         HClass oldn, newn;
278 bdemsky  1.1.2.26         WorkSet done;
279 bdemsky  1.1.2.26         ChangingVisitor(HClass oldn, HClass newn) {
280 bdemsky  1.1.2.26             this.oldn=oldn;
281 bdemsky  1.1.2.26             this.newn=newn;
282 bdemsky  1.1.2.26         }
283 bdemsky  1.1.2.26 
284 bdemsky  1.1.2.26         public void visit(Quad q) {
285 bdemsky  1.1.2.26             done.add(q);
286 bdemsky  1.1.2.26         }
287 bdemsky  1.1.2.26 
288 bdemsky  1.1.2.26         public void visit(GET q) {
289 bdemsky  1.1.2.26             if (q.field().getDeclaringClass()==oldn) {
290 bdemsky  1.1.2.26                 HField hfield=
291 bdemsky  1.1.2.26                     newn.getDeclaredField(q.field().getName());
292 bdemsky  1.1.2.26                 GET get=new GET(q.getFactory(),q,
293 bdemsky  1.1.2.26                                 q.dst(),hfield,q.objectref());
294 bdemsky  1.1.2.26                 done.add(get);
295 bdemsky  1.1.2.26                 Quad.addEdge(q.prev(0),q.prevEdge(0).which_succ(),
296 bdemsky  1.1.2.26                              get,0);
297 bdemsky  1.1.2.26                 Quad.addEdge(get,0,
298 bdemsky  1.1.2.26                              q.next(0),q.nextEdge(0).which_pred());
299 bdemsky  1.1.2.26             }
300 bdemsky  1.1.2.26         }
301 bdemsky  1.1.2.26 
302 bdemsky  1.1.2.26         public void visit(SET q) {
303 bdemsky  1.1.2.26             if (q.field().getDeclaringClass()==oldn) {
304 bdemsky  1.1.2.26                 HField hfield=
305 bdemsky  1.1.2.26                     newn.getDeclaredField(q.field().getName());
306 bdemsky  1.1.2.26                 SET set=new SET(q.getFactory(),q,
307 bdemsky  1.1.2.26                                 hfield,q.objectref(),q.src());
308 bdemsky  1.1.2.26                 done.add(set);
309 bdemsky  1.1.2.26                 Quad.addEdge(q.prev(0),q.prevEdge(0).which_succ(),
310 bdemsky  1.1.2.26                              set,0);
311 bdemsky  1.1.2.26                 Quad.addEdge(set,0,
312 bdemsky  1.1.2.26                              q.next(0),q.nextEdge(0).which_pred());
313 bdemsky  1.1.2.26             }
314 bdemsky  1.1.2.26         }
315 bdemsky  1.1.2.26 
316 bdemsky  1.1.2.26         public void reName(Quad q) {
317 bdemsky  1.1.2.26             done=new WorkSet();
318 bdemsky  1.1.2.26             WorkSet todo=new WorkSet();
319 bdemsky  1.1.2.26             todo.add(q);
320 bdemsky  1.1.2.26             while(!todo.isEmpty()) {
321 bdemsky  1.1.2.26                 Quad qq=(Quad)todo.pop();
322 bdemsky  1.1.2.26                 Quad[] next=qq.next();
323 bdemsky  1.1.2.26                 for(int i=0;i<next.length;i++)
324 bdemsky  1.1.2.26                     if (!done.contains(next[i]))
325 bdemsky  1.1.2.26                         todo.add(next[i]);
326 bdemsky  1.1.2.26                 qq.accept(this);
327 bdemsky  1.1.2.26             }
328 bdemsky  1.1.2.26         }
329 bdemsky  1.1.2.26     }
330 bdemsky  1.1.2.26 
331 bdemsky  1.1.2.25 
332 bdemsky  1.1.2.25 
333 bdemsky  1.1.2.8      // create asynchronous version of HMethod to replace blocking version
334 bdemsky  1.1.2.8      // does not create HCode that goes w/ it...
335 bdemsky  1.1.2.51     static HMethod makeAsync(Map old2new, HMethod original,
336 bdemsky  1.1.2.57                               CachingCodeFactory ucf, Linker linker,boolean optimistic)
337 bdemsky  1.1.2.8      {
338 bdemsky  1.1.2.8          //      final HMethod original = blocking.method();
339 bdemsky  1.1.2.25         HClass originalClass = original.getDeclaringClass();
340 bdemsky  1.1.2.62         System.out.println("Getting mutator for :"+originalClass);
341 bdemsky  1.1.2.25         HClassMutator originalMutator=originalClass.getMutator();
342 cananian 1.3.2.1          assert originalMutator!=null;
343 bdemsky  1.1.2.49   
344 bdemsky  1.1.2.8          // use the return type of the original HMethod to get the String 
345 bdemsky  1.1.2.8          // prefix for the type of Continuation we want as the new return type
346 bdemsky  1.1.2.8          final String pref = ContBuilder.getPrefix(original.getReturnType());
347 bdemsky  1.1.2.8  
348 bdemsky  1.1.2.8          // get the return type for the replacement HMethod
349 bdemsky  1.1.2.25         final HClass newReturnType = linker.forName
350 bdemsky  1.1.2.13             ("harpoon.Analysis.ContBuilder." + pref + "Continuation");
351 bdemsky  1.1.2.8  
352 bdemsky  1.1.2.8          // find a unique name for the replacement HMethod
353 bdemsky  1.1.2.57         String methodNamePrefix = original.getName() + ((optimistic)?"AsyncO":"Async");
354 bdemsky  1.1.2.8          String newMethodName = methodNamePrefix;
355 bdemsky  1.1.2.39         boolean threadrun=false;
356 bdemsky  1.1.2.60         boolean createmethod=true;
357 bdemsky  1.1.2.25         if (linker.forName("java.lang.Runnable").
358 bdemsky  1.1.2.22             isSuperinterfaceOf(originalClass)&&
359 bdemsky  1.1.2.22             originalClass.getMethod("run",new HClass[0]).equals(original)) {
360 bdemsky  1.1.2.8              try {
361 bdemsky  1.1.2.58                 newMethodName = "run_Async";
362 bdemsky  1.1.2.34                 originalClass.getDeclaredMethod(newMethodName, 
363 bdemsky  1.1.2.8                                             original.getParameterTypes());
364 bdemsky  1.1.2.39                 if (originalClass.getName().compareTo("java.lang.Thread")!=0)
365 bdemsky  1.1.2.39                     throw new RuntimeException("Name collision with run_Async method");
366 bdemsky  1.1.2.39                 else
367 bdemsky  1.1.2.39                     threadrun=true;
368 bdemsky  1.1.2.8              } catch (NoSuchMethodError e) {
369 bdemsky  1.1.2.22             }
370 bdemsky  1.1.2.22         } else {
371 bdemsky  1.1.2.34             try {
372 bdemsky  1.1.2.58                 newMethodName = methodNamePrefix; 
373 bdemsky  1.1.2.34                 originalClass.getDeclaredMethod(newMethodName, 
374 bdemsky  1.1.2.34                                         original.getParameterTypes());
375 bdemsky  1.1.2.61                 throw new RuntimeException("Name collision with "+newMethodName+ " method");
376 bdemsky  1.1.2.61                 //System.out.println("Name collision with "+newMethodName+ " method");
377 bdemsky  1.1.2.61                 //createmethod=false;
378 bdemsky  1.1.2.61                 //old2new.put(original,originalClass.getDeclaredMethod(newMethodName, original.getParameterTypes()));
379 bdemsky  1.1.2.34             } catch (NoSuchMethodError e) {
380 bdemsky  1.1.2.8              }
381 bdemsky  1.1.2.8          }
382 bdemsky  1.1.2.8          // create replacement method
383 bdemsky  1.1.2.32         HMethod replacement=null;
384 bdemsky  1.1.2.60         if (createmethod&&(!threadrun)) {
385 bdemsky  1.1.2.32             replacement=originalMutator.addDeclaredMethod(newMethodName, 
386 bdemsky  1.1.2.32                                                           original.getParameterTypes(),
387 bdemsky  1.1.2.32                                                           newReturnType);
388 bdemsky  1.1.2.32             HMethodMutator rmutator=replacement.getMutator();
389 bdemsky  1.1.2.32             rmutator.setExceptionTypes(original.getExceptionTypes());
390 bdemsky  1.1.2.62             rmutator.setModifiers(original.getModifiers()^(original.getModifiers() & Modifier.NATIVE));
391 bdemsky  1.1.2.32             rmutator.setParameterNames(original.getParameterNames());
392 bdemsky  1.1.2.32             rmutator.setSynthetic(original.isSynthetic());
393 bdemsky  1.1.2.39         } else {
394 bdemsky  1.1.2.39             replacement=originalClass.getDeclaredMethod(newMethodName,
395 bdemsky  1.1.2.39                                                         original.getParameterTypes());
396 bdemsky  1.1.2.32             HMethodMutator rmutator=replacement.getMutator();
397 bdemsky  1.1.2.32             rmutator.setReturnType(newReturnType);
398 bdemsky  1.1.2.32         }
399 bdemsky  1.1.2.60         if (createmethod)
400 bdemsky  1.1.2.60             old2new.put(original, replacement);
401 bdemsky  1.1.2.8          return replacement;
402 bdemsky  1.1.2.8      }
403 bdemsky  1.1.2.3  
404 bdemsky  1.1.2.8      // creates the HClass and constructor for the continuation
405 bdemsky  1.1.2.51     static HClass createContinuation(HMethod blocking, CALL callsite,
406 bdemsky  1.1.2.55                                       CachingCodeFactory ucf, Linker linker,
407 bdemsky  1.1.2.55                                      HClass environment) 
408 bdemsky  1.1.2.8          throws NoClassDefFoundError
409 bdemsky  1.1.2.8      {
410 bdemsky  1.1.2.8          final HClass template = 
411 bdemsky  1.1.2.25             linker.forName("harpoon.Analysis.ContBuilder.ContTemplate");
412 bdemsky  1.1.2.8  
413 bdemsky  1.1.2.25         String cname=UniqueName.uniqueClassName("harpoon.Analysis.ContBuilder.ContTemplate"
414 bdemsky  1.1.2.25                                                 ,linker);
415 bdemsky  1.1.2.25         HClass continuationClass = linker.createMutableClass(cname,template);
416 cananian 1.3.2.1          assert template.getLinker()==linker &&
417 cananian 1.3.2.1                      continuationClass.getLinker()==linker;
418 bdemsky  1.1.2.25         HClassMutator contMutator=continuationClass.getMutator();
419 bdemsky  1.1.2.55 
420 bdemsky  1.1.2.55         //Environment field
421 bdemsky  1.1.2.55         HField envf=contMutator.addDeclaredField("e",environment);
422 bdemsky  1.1.2.55         HMethod hconst=continuationClass.getConstructor(new HClass[0]);
423 bdemsky  1.1.2.55         hconst.getMutator().setParameterTypes(new HClass[]{environment});
424 bdemsky  1.1.2.55         
425 bdemsky  1.1.2.59 
426 bdemsky  1.1.2.59 
427 bdemsky  1.1.2.59 
428 bdemsky  1.1.2.59         // use the return type of the blocking HMethod to get the String 
429 bdemsky  1.1.2.59         // prefix for the superclass for the continuation we want to create
430 bdemsky  1.1.2.59         final String superPref = 
431 bdemsky  1.1.2.59             ContBuilder.getPrefix(blocking.getReturnType());
432 bdemsky  1.1.2.59 
433 bdemsky  1.1.2.59         // get the superclass for the continuation
434 bdemsky  1.1.2.59         final HClass superclass = linker.forName
435 bdemsky  1.1.2.59             ("harpoon.Analysis.ContBuilder." + superPref + "Continuation");
436 bdemsky  1.1.2.59 
437 bdemsky  1.1.2.59 
438 bdemsky  1.1.2.59 
439 bdemsky  1.1.2.59 
440 bdemsky  1.1.2.59 
441 bdemsky  1.1.2.55         ContCodeSSI ccssi=new ContCodeSSI(hconst);
442 bdemsky  1.1.2.59         TempFactory tf=ccssi.getFactory().tempFactory();
443 bdemsky  1.1.2.59         Temp tenv=new Temp(tf),
444 bdemsky  1.1.2.59             tthis=new Temp(tf);
445 bdemsky  1.1.2.55         HEADER header=new HEADER(ccssi.getFactory(),null);
446 bdemsky  1.1.2.55         METHOD method=new METHOD(ccssi.getFactory(),null,
447 bdemsky  1.1.2.55                                  new Temp[] {tthis,tenv},1);
448 bdemsky  1.1.2.59         
449 bdemsky  1.1.2.59         Temp t1=new Temp(tf),t2=new Temp(tf),retex=new Temp(tf);
450 bdemsky  1.1.2.59         CALL call =new CALL(ccssi.getFactory(),null,superclass.getConstructor(new HClass[0]), 
451 bdemsky  1.1.2.59                             new Temp[] {tthis},null,retex,false,false,
452 bdemsky  1.1.2.59                             new Temp[][] {{t1,new Temp(tf)},{t2,new Temp(tf)}},new Temp[] {tthis, tenv});
453 bdemsky  1.1.2.59         tthis=t1;tenv=t2;
454 bdemsky  1.1.2.59         THROW qthrow=new THROW(ccssi.getFactory(),null,retex);
455 bdemsky  1.1.2.55         SET set=new SET(ccssi.getFactory(),null,envf,tthis,tenv);
456 bdemsky  1.1.2.55         RETURN qreturn=new RETURN(ccssi.getFactory(),null,null); 
457 bdemsky  1.1.2.59         FOOTER footer=new FOOTER(ccssi.getFactory(),null,3);
458 bdemsky  1.1.2.59 
459 bdemsky  1.1.2.55         Quad.addEdge(header,0,footer,0);
460 bdemsky  1.1.2.55         Quad.addEdge(header,1,method,0);
461 bdemsky  1.1.2.59         Quad.addEdge(method,0,call,0);
462 bdemsky  1.1.2.59         Quad.addEdge(call,0,set,0);
463 bdemsky  1.1.2.55         Quad.addEdge(set,0,qreturn,0);
464 bdemsky  1.1.2.55         Quad.addEdge(qreturn,0,footer,1);
465 bdemsky  1.1.2.59         Quad.addEdge(call,1,qthrow,0);
466 bdemsky  1.1.2.59         Quad.addEdge(qthrow,0,footer,2);
467 bdemsky  1.1.2.59         
468 bdemsky  1.1.2.55         ccssi.quadSet(header);
469 bdemsky  1.1.2.55         
470 bdemsky  1.1.2.59         
471 bdemsky  1.1.2.55         ucf.put(hconst, ccssi);
472 bdemsky  1.1.2.55 
473 bdemsky  1.1.2.25             //new HClassSyn(template);
474 bdemsky  1.1.2.8          final int numConstructors = continuationClass.getConstructors().length;
475 cananian 1.3.2.1          assert numConstructors == 1 : "Found " + numConstructors + " constructors in " +
476 cananian 1.3.2.1                      "ContTemplate. Expected one";
477 bdemsky  1.1.2.8  
478 bdemsky  1.1.2.8  
479 bdemsky  1.1.2.25         contMutator.setSuperclass(superclass);
480 bdemsky  1.1.2.8  
481 bdemsky  1.1.2.8          // we want the return type of the blocking call
482 bdemsky  1.1.2.8          // this gives us the interface that our continuation should implement
483 bdemsky  1.1.2.8          final String interPref = 
484 bdemsky  1.1.2.8              ContBuilder.getPrefix(callsite.method().getReturnType());
485 bdemsky  1.1.2.8  
486 bdemsky  1.1.2.8          // get the interface that the continuation needs to implement
487 bdemsky  1.1.2.25         final HClass inter = linker.forName("harpoon.Analysis.ContBuilder." + 
488 bdemsky  1.1.2.8                                              interPref + "ResultContinuation");
489 bdemsky  1.1.2.27         contMutator.addInterface(inter);
490 bdemsky  1.1.2.25 
491 bdemsky  1.1.2.25         HMethod hmethods[]=template.getDeclaredMethods();
492 bdemsky  1.1.2.25         for(int i=0;i<hmethods.length;i++) {
493 bdemsky  1.1.2.55             if (!hmethods[i].getName().equals("<init>"))
494 bdemsky  1.1.2.55                 try {
495 bdemsky  1.1.2.55                     HMethod nhm=continuationClass
496 bdemsky  1.1.2.55                         .getDeclaredMethod(hmethods[i].getName(),
497 bdemsky  1.1.2.55                                            hmethods[i].getDescriptor());
498 cananian 1.1.2.64                     HCode hchc = ((Code)ucf.convert(hmethods[i])).clone(nhm)
499 cananian 1.1.2.64                         .hcode();
500 bdemsky  1.1.2.55                     (new ChangingVisitor(template,continuationClass))
501 bdemsky  1.1.2.55                         .reName((Quad)hchc.getRootElement());
502 bdemsky  1.1.2.55                     ucf.put(nhm, hchc);
503 bdemsky  1.1.2.55                 } catch (NoSuchMethodError e) {
504 bdemsky  1.1.2.55                     System.err.println(e);
505 bdemsky  1.1.2.55                 }
506 bdemsky  1.1.2.8          }
507 bdemsky  1.1.2.8  
508 bdemsky  1.1.2.25         HMethod hm = continuationClass.getDeclaredMethod("resume", new HClass[0]);
509 bdemsky  1.1.2.25         HMethodMutator hmMutator=hm.getMutator();
510 bdemsky  1.1.2.25 
511 bdemsky  1.1.2.8          // get the return value of the blocking call
512 bdemsky  1.1.2.8          // this is the parameter of the resume method, if any
513 bdemsky  1.1.2.8          HClass rettype = callsite.method().getReturnType();
514 bdemsky  1.1.2.8          Temp retval = callsite.retval();
515 bdemsky  1.1.2.8          boolean hasParameter = false;
516 bdemsky  1.1.2.8          if (retval != null) {
517 bdemsky  1.1.2.8              hasParameter = true;
518 bdemsky  1.1.2.8              String[] parameterNames = new String[1];
519 bdemsky  1.1.2.8              parameterNames[0] = retval.name();
520 bdemsky  1.1.2.8              HClass[] parameterTypes = new HClass[1];
521 bdemsky  1.1.2.8              if (rettype.isPrimitive())
522 bdemsky  1.1.2.8                  parameterTypes[0] = rettype;
523 bdemsky  1.1.2.8              else {
524 bdemsky  1.1.2.25                 parameterTypes[0] = linker.forName("java.lang.Object");
525 bdemsky  1.1.2.8              }
526 bdemsky  1.1.2.25             hmMutator.setParameterNames(parameterNames);
527 bdemsky  1.1.2.25             hmMutator.setParameterTypes(parameterTypes);
528 bdemsky  1.1.2.8          }
529 bdemsky  1.1.2.8          return continuationClass;
530 kkz      1.1.2.1      }
531 cananian 1.2      }