1 cananian 1.1.2.7  // Method.java, created Sat Mar 27 17:05:09 1999 by duncan
  2 cananian 1.1.2.6  // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.6  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 duncan   1.1.2.1  package harpoon.Interpret.Tree;
  5 duncan   1.1.2.1  
  6 cananian 1.1.2.19 import harpoon.Analysis.Maps.Derivation;
  7 duncan   1.1.2.1  import harpoon.Analysis.Maps.TypeMap;
  8 duncan   1.1.2.1  import harpoon.Backend.Generic.Frame;
  9 duncan   1.1.2.1  import harpoon.ClassFile.CachingCodeFactory;
 10 duncan   1.1.2.1  import harpoon.ClassFile.HClass;
 11 duncan   1.1.2.1  import harpoon.ClassFile.HCode;
 12 duncan   1.1.2.1  import harpoon.ClassFile.HCodeFactory;
 13 duncan   1.1.2.1  import harpoon.ClassFile.HConstructor;
 14 duncan   1.1.2.1  import harpoon.ClassFile.HField;
 15 duncan   1.1.2.1  import harpoon.ClassFile.HMethod;
 16 cananian 1.1.2.16 import harpoon.ClassFile.Linker;
 17 duncan   1.1.2.1  import harpoon.IR.Tree.BINOP;
 18 duncan   1.1.2.8  import harpoon.IR.Tree.Bop;
 19 duncan   1.1.2.1  import harpoon.IR.Tree.CALL;
 20 duncan   1.1.2.8  import harpoon.IR.Tree.Code;
 21 duncan   1.1.2.1  import harpoon.IR.Tree.CJUMP;
 22 duncan   1.1.2.1  import harpoon.IR.Tree.CONST;
 23 cananian 1.1.2.15 import harpoon.IR.Tree.DATUM;
 24 duncan   1.1.2.14 //import harpoon.IR.Tree.Edge;
 25 duncan   1.1.2.1  import harpoon.IR.Tree.ESEQ;
 26 jwhaley  1.1.2.21 import harpoon.IR.Tree.EXPR;
 27 duncan   1.1.2.1  import harpoon.IR.Tree.Exp;
 28 duncan   1.1.2.1  import harpoon.IR.Tree.ExpList;
 29 duncan   1.1.2.1  import harpoon.IR.Tree.INVOCATION;
 30 duncan   1.1.2.1  import harpoon.IR.Tree.JUMP;
 31 duncan   1.1.2.1  import harpoon.IR.Tree.LABEL;
 32 duncan   1.1.2.1  import harpoon.IR.Tree.MEM;
 33 duncan   1.1.2.8  import harpoon.IR.Tree.METHOD;
 34 duncan   1.1.2.1  import harpoon.IR.Tree.MOVE;
 35 duncan   1.1.2.1  import harpoon.IR.Tree.NAME;
 36 duncan   1.1.2.1  import harpoon.IR.Tree.NATIVECALL;
 37 duncan   1.1.2.1  import harpoon.IR.Tree.OPER;
 38 duncan   1.1.2.1  import harpoon.IR.Tree.RETURN;
 39 duncan   1.1.2.9  import harpoon.IR.Tree.SEGMENT;
 40 duncan   1.1.2.1  import harpoon.IR.Tree.SEQ;
 41 duncan   1.1.2.1  import harpoon.IR.Tree.Stm;
 42 duncan   1.1.2.1  import harpoon.IR.Tree.TEMP;
 43 duncan   1.1.2.1  import harpoon.IR.Tree.THROW;
 44 duncan   1.1.2.1  import harpoon.IR.Tree.Tree;
 45 duncan   1.1.2.8  import harpoon.IR.Tree.TreeKind;
 46 duncan   1.1.2.1  import harpoon.IR.Tree.TreeVisitor;
 47 duncan   1.1.2.1  import harpoon.IR.Tree.Type;
 48 duncan   1.1.2.1  import harpoon.IR.Tree.UNOP;
 49 duncan   1.1.2.1  import harpoon.IR.Tree.Uop;
 50 duncan   1.1.2.1  import harpoon.Temp.Label;
 51 duncan   1.1.2.1  import harpoon.Temp.Temp;
 52 duncan   1.1.2.1  import harpoon.Util.Util;
 53 duncan   1.1.2.1  
 54 duncan   1.1.2.1  import java.lang.reflect.Modifier;
 55 duncan   1.1.2.1  import java.io.PrintWriter;
 56 duncan   1.1.2.1  import java.util.Enumeration;
 57 duncan   1.1.2.1  import java.util.Hashtable;
 58 duncan   1.1.2.1  import java.util.Stack;
 59 duncan   1.1.2.1  import java.util.Vector;
 60 duncan   1.1.2.1  
 61 duncan   1.1.2.1  /**
 62 duncan   1.1.2.1   * <code>Method</code> converts <code>HMethods</code> into tree code, 
 63 duncan   1.1.2.1   * and interprets them. 
 64 duncan   1.1.2.1   * 
 65 duncan   1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 66 cananian 1.4       * @version $Id: Method.java,v 1.4 2002/04/10 03:06:00 cananian Exp $
 67 duncan   1.1.2.1   */
 68 cananian 1.1.2.16 public final class Method extends Debug {
 69 duncan   1.1.2.2      static PrintWriter out = new java.io.PrintWriter(System.out);
 70 duncan   1.1.2.1      static final Integer TREE_NULL = new Integer(0);
 71 duncan   1.1.2.5  
 72 duncan   1.1.2.1      /** invoke a static main method with no static state. */
 73 duncan   1.1.2.1      public static final void run(PrintWriter prof, 
 74 duncan   1.1.2.1                                   HCodeFactory hcf,
 75 duncan   1.1.2.1                                   HClass cls, String[] args) {
 76 duncan   1.1.2.5          Code        tc;       // The code of the method to interpret
 77 duncan   1.1.2.5          HMethod     method;   // The method to interpret
 78 duncan   1.1.2.5          OffsetMap   map;      // The offset map used by the tree interpreter
 79 duncan   1.1.2.5          StaticState ss;       // The interpreter's static state
 80 duncan   1.1.2.1  
 81 cananian 1.1.2.16         Linker linker = cls.getLinker();
 82 cananian 1.1.2.16         method=cls.getMethod("main", new HClass[] { linker.forDescriptor("[Ljava/lang/String;") });
 83 duncan   1.1.2.1          
 84 cananian 1.3.2.1          assert method.isStatic();
 85 cananian 1.3.2.1          assert hcf.getCodeName().equals("canonical-tree") ||
 86 cananian 1.3.2.1                      hcf.getCodeName().equals("optimized-tree") : "Bad factory codename: " + hcf.getCodeName();
 87 duncan   1.1.2.1          
 88 duncan   1.1.2.5          tc = (Code)hcf.convert(method);
 89 cananian 1.1.2.17         map=((DefaultFrame)((Tree)tc.getRootElement()).getFactory().getFrame()).getOffsetMap();
 90 cananian 1.1.2.16         ss = new StaticState(linker, hcf, prof, (InterpreterOffsetMap)map);
 91 duncan   1.1.2.1          try {
 92 cananian 1.1.2.16             HMethod HMinit = ss.HCsystem.getMethod("initializeSystemClass","()V");
 93 duncan   1.1.2.1              // set up static state.
 94 cananian 1.1.2.16             ss.load(ss.HCsystem);
 95 duncan   1.1.2.1              invoke(ss, HMinit, new Object[0]);
 96 duncan   1.1.2.1              // encapsulate params properly.
 97 cananian 1.1.2.16             ArrayRef params=new ArrayRef(ss,ss.HCstringA,new int[]{args.length});
 98 duncan   1.1.2.1              for (int i=0; i<args.length; i++)
 99 duncan   1.1.2.1                  params.update(i, ss.makeString(args[i]));
100 duncan   1.1.2.1              // run main() method.
101 duncan   1.1.2.1              ss.load(cls);
102 duncan   1.1.2.1                      
103 duncan   1.1.2.1              invoke(ss, method, new Object[] { toNonNativeFormat(params) } );
104 duncan   1.1.2.1          } catch (InterpretedThrowable it) {
105 duncan   1.1.2.1              String msg = it.ex.type.getName();
106 duncan   1.1.2.1              try {
107 duncan   1.1.2.1                  HMethod hm = it.ex.type.getMethod("toString",new HClass[0]);
108 duncan   1.1.2.1                  ObjectRef obj =(ObjectRef)invoke(ss, hm, new Object[]{it.ex});
109 duncan   1.1.2.1                  msg = ss.ref2str(obj);
110 duncan   1.1.2.1              } catch (InterpretedThrowable it0) { /* do nothing */ }
111 duncan   1.1.2.1              PrintWriter err = new PrintWriter(System.err, true);
112 duncan   1.1.2.1              err.println("Caught "+msg);
113 duncan   1.1.2.1              //StaticState.printStackTrace(err, it.stackTrace);
114 duncan   1.1.2.1              StaticState.printStackTrace(err, (String[]) it.ex.getClosure());
115 duncan   1.1.2.5          } 
116 duncan   1.1.2.5          finally {
117 duncan   1.1.2.1              // try to force finalization of object classes
118 duncan   1.1.2.3              if (DEBUG) db("Try to force finalization...");
119 duncan   1.1.2.1              ss=null;
120 duncan   1.1.2.1              System.gc();
121 duncan   1.1.2.1              System.runFinalization();
122 duncan   1.1.2.1          }
123 duncan   1.1.2.1      }
124 duncan   1.1.2.1  
125 duncan   1.1.2.1      /** Returns the value obtained by converting <code>obj</code> into 
126 duncan   1.1.2.1       *  native format.  The <code>type</code> parameter is the type
127 duncan   1.1.2.1       *  of the <code>obj</code> parameter.  
128 duncan   1.1.2.1       */
129 duncan   1.1.2.1      static final Object toNativeFormat(Object obj, HClass type) { 
130 duncan   1.1.2.3          Object  retval = null;
131 duncan   1.1.2.3          Pointer ptr    = null;
132 duncan   1.1.2.3  
133 duncan   1.1.2.3          if (DEBUG) db("TONF: " + obj + ", " + type);
134 duncan   1.1.2.3  
135 duncan   1.1.2.3          try { ptr = (Pointer)obj; }
136 duncan   1.1.2.3          catch (ClassCastException e) { 
137 duncan   1.1.2.8              // obj is not a pointer type.  In that case, we _must_ have
138 duncan   1.1.2.8              // specified its type through the "type" parameter.
139 cananian 1.3.2.1              assert type!=null;
140 duncan   1.1.2.3              if (type == HClass.Byte)
141 duncan   1.1.2.3                  retval = new Byte((byte)((Integer)obj).intValue());
142 duncan   1.1.2.3              else if (type == HClass.Short)
143 duncan   1.1.2.3                  retval = new Short((short)((Integer)obj).intValue());
144 duncan   1.1.2.3              else if (type == HClass.Char)
145 duncan   1.1.2.3                  retval = new Character((char)((Integer)obj).intValue());
146 duncan   1.1.2.3              else if (type == HClass.Boolean)
147 duncan   1.1.2.3                  retval = new Boolean(((Integer)obj).intValue()!=0);
148 duncan   1.1.2.3              else if (!type.isPrimitive())  {
149 cananian 1.3.2.1                  assert ((Integer)obj).intValue()==0;
150 duncan   1.1.2.3                  retval = null;
151 duncan   1.1.2.3              }
152 duncan   1.1.2.3              else 
153 duncan   1.1.2.3                  retval = obj;
154 duncan   1.1.2.1  
155 duncan   1.1.2.3              return retval;
156 duncan   1.1.2.3          }
157 duncan   1.1.2.3              
158 duncan   1.1.2.3          // obj must be a Pointer
159 duncan   1.1.2.3          switch (ptr.kind()) { 
160 duncan   1.1.2.3          case Pointer.ARRAY_PTR:
161 duncan   1.1.2.3              retval = ((ArrayPointer)obj).getBase();  // --> ArrayRef
162 duncan   1.1.2.3              break;
163 duncan   1.1.2.3          case Pointer.CONST_PTR:
164 duncan   1.1.2.3              ConstPointer cptr = (ConstPointer)obj; 
165 duncan   1.1.2.3              retval = toNativeFormat(cptr.getValue(), cptr.getType());
166 duncan   1.1.2.3              break;
167 duncan   1.1.2.3          case Pointer.FIELD_PTR:
168 duncan   1.1.2.3              retval = ((FieldPointer)obj).getBase();  // --> ObjectRef
169 duncan   1.1.2.3              break;
170 duncan   1.1.2.3          default: 
171 duncan   1.1.2.3              // Cannot convert any other type of pointer
172 duncan   1.1.2.3              throw new Error("Can't convert " + ptr.getClass().toString() +
173 duncan   1.1.2.3                              " to native format");
174 duncan   1.1.2.3          }
175 duncan   1.1.2.3  
176 duncan   1.1.2.3          if (DEBUG) db("   --> " + retval);
177 duncan   1.1.2.3          return retval;
178 duncan   1.1.2.3      } 
179 duncan   1.1.2.3     
180 duncan   1.1.2.1      /** Returns the value obtained by converting <code>obj</code> into 
181 duncan   1.1.2.1       *  non-native format. 
182 duncan   1.1.2.1       */
183 duncan   1.1.2.1      static final Object toNonNativeFormat(Object obj) { 
184 cananian 1.3.2.1          assert !(obj instanceof UndefinedRef);
185 duncan   1.1.2.1  
186 duncan   1.1.2.3          Object result;
187 duncan   1.1.2.3  
188 duncan   1.1.2.3          if (DEBUG) db("TONNF: " + obj);
189 duncan   1.1.2.3  
190 duncan   1.1.2.1          if (obj ==null) 
191 duncan   1.1.2.3              result = TREE_NULL;
192 duncan   1.1.2.1          else if (obj instanceof ObjectRef)
193 duncan   1.1.2.3              result = new FieldPointer((ObjectRef)obj, 0);
194 duncan   1.1.2.1          else if (obj instanceof ArrayRef) 
195 duncan   1.1.2.3              result = new ArrayPointer((ArrayRef)obj, 0);
196 duncan   1.1.2.1          else if (obj instanceof Byte ||
197 duncan   1.1.2.1                   obj instanceof Short)
198 duncan   1.1.2.3              result = new Integer(((Number)obj).intValue());
199 duncan   1.1.2.1          else if (obj instanceof Character)
200 duncan   1.1.2.3              result = new Integer((int)((Character)obj).charValue());
201 duncan   1.1.2.1          else if (obj instanceof Boolean)
202 duncan   1.1.2.3              result = new Integer(((Boolean)obj).booleanValue()?1:0);
203 duncan   1.1.2.1          else 
204 duncan   1.1.2.3              result = obj;
205 duncan   1.1.2.3  
206 duncan   1.1.2.3          if (DEBUG) db("   ---> " + result);
207 duncan   1.1.2.3  
208 duncan   1.1.2.3          return result;
209 duncan   1.1.2.1      }
210 duncan   1.1.2.1  
211 duncan   1.1.2.1      /** invoke the specified method.  void methods return null. */
212 duncan   1.1.2.1      static final Object invoke(StaticState ss, HMethod method, Object[] params)
213 duncan   1.1.2.1          throws InterpretedThrowable {
214 cananian 1.3.2.1          assert params.length == numParams(method);
215 duncan   1.1.2.2  
216 duncan   1.1.2.2          if (DEBUG) db("Invoking method: " + method);
217 duncan   1.1.2.2  
218 duncan   1.1.2.1          if (!ss.isLoaded(method.getDeclaringClass())) {
219 duncan   1.1.2.1              // Do a dummy push in case an error occurs when loading the class
220 duncan   1.1.2.1              ss.pushStack(new NativeStackFrame(method)); 
221 duncan   1.1.2.1              ss.load(method.getDeclaringClass());
222 duncan   1.1.2.1              ss.popStack();  // don't want this stack frame
223 duncan   1.1.2.1          }
224 duncan   1.1.2.1  
225 duncan   1.1.2.1          long start_count = ss.getInstructionCount();
226 duncan   1.1.2.1          try { 
227 duncan   1.1.2.1              // pop stack, end profiling, etc.
228 duncan   1.1.2.1              // easy to verify that every path through try executes
229 duncan   1.1.2.1              // pushStack *exactly once*.
230 duncan   1.1.2.1            
231 duncan   1.1.2.1              NativeMethod nm = ss.findNative(method);
232 duncan   1.1.2.1              if (nm!=null) {
233 duncan   1.1.2.1                  ss.pushStack(new NativeStackFrame(method));
234 duncan   1.1.2.1                  //ss.incrementInstructionCount(); //native methods take 0 time
235 duncan   1.1.2.1                  Object rval = nm.invoke(ss, params);
236 duncan   1.1.2.2                  if (DEBUG) db("Returning: " + rval);
237 duncan   1.1.2.1                  return rval;
238 duncan   1.1.2.1              }
239 duncan   1.1.2.1              // non-native, interpret.
240 duncan   1.1.2.5              Code c = (Code)ss.hcf.convert(method);
241 duncan   1.1.2.1              Frame f = ((Tree)c.getRootElement()).getFactory().getFrame();
242 duncan   1.1.2.1  
243 duncan   1.1.2.1              // failed to translate method into tree code
244 duncan   1.1.2.1              if (c==null) {
245 duncan   1.1.2.1                  ss.pushStack(new NativeStackFrame(method)); // gonna pop it
246 cananian 1.1.2.16                 ObjectRef obj = ss.makeThrowable(ss.HCunsatisfiedlinkErr,
247 duncan   1.1.2.1                                                   "No definition for "+method);
248 duncan   1.1.2.1                  throw new InterpretedThrowable(obj, ss);
249 duncan   1.1.2.1              }
250 duncan   1.1.2.2              if (Method.DEBUG) c.print(out);
251 duncan   1.1.2.1  
252 duncan   1.1.2.1              // push new stack frame
253 duncan   1.1.2.1              TreeStackFrame sf = new TreeStackFrame((Stm)c.getRootElement());
254 duncan   1.1.2.1              ss.pushStack(sf);
255 duncan   1.1.2.1  
256 duncan   1.1.2.8              Interpreter i = new TreeInterpreter(ss, sf, params);
257 duncan   1.1.2.2              
258 duncan   1.1.2.1              // Run interpreter on the generated tree code
259 cananian 1.1.2.12             while (!i.done) { sf.pc.accept(i); }
260 duncan   1.1.2.1  
261 duncan   1.1.2.1              // We've finished, see if an exception was thrown
262 duncan   1.1.2.1              if (i.Texc!=TREE_NULL) {
263 duncan   1.1.2.1                  System.err.println("THROWING " +
264 duncan   1.1.2.1                                     ((ObjectRef)i.Texc).type +
265 duncan   1.1.2.1                                     " at " + sf.pc.getSourceFile() + ":" +
266 duncan   1.1.2.1                                     sf.pc.getLineNumber());
267 duncan   1.1.2.1                  throw new InterpretedThrowable((ObjectRef)i.Texc, ss);
268 duncan   1.1.2.1              }
269 duncan   1.1.2.1              
270 duncan   1.1.2.2              if (method.getReturnType()==HClass.Void) {
271 duncan   1.1.2.2                  if (DEBUG) db("Returning from VOID func");
272 duncan   1.1.2.2                  return null;
273 duncan   1.1.2.2              }
274 duncan   1.1.2.1              else {
275 duncan   1.1.2.3                  if (DEBUG) db("Returning: " + i.Tret);
276 duncan   1.1.2.1                  // Convert to native format, and return
277 duncan   1.1.2.1                  return toNativeFormat(i.Tret, method.getReturnType());
278 duncan   1.1.2.1              }
279 duncan   1.1.2.1          }
280 duncan   1.1.2.1          finally { 
281 duncan   1.1.2.1              // pop stack & profile *always.*
282 duncan   1.1.2.2              //if (DEBUG) db("Finished: " + method.getName());
283 duncan   1.1.2.1              ss.popStack();
284 duncan   1.1.2.1              long end_count = ss.getInstructionCount();
285 duncan   1.1.2.1              ss.profile(method, start_count, end_count);
286 duncan   1.1.2.1          }
287 duncan   1.1.2.1      }
288 duncan   1.1.2.1  
289 duncan   1.1.2.1      private static int numParams(HMethod m) {
290 duncan   1.1.2.1          return m.getParameterTypes().length + (m.isStatic()?0:1);
291 duncan   1.1.2.1      }
292 duncan   1.1.2.1  
293 duncan   1.1.2.1      // Interpreter superclass.  Not strictly necessary, but it saved
294 duncan   1.1.2.1      // work to reuse as much of Scott's code as possible. 
295 duncan   1.1.2.1      static private abstract class Interpreter extends TreeVisitor {
296 duncan   1.1.2.1          final StaticState ss;
297 duncan   1.1.2.1          final TreeStackFrame sf;
298 duncan   1.1.2.1          Object Tret = TREE_NULL;
299 duncan   1.1.2.1          Object Texc = TREE_NULL;
300 duncan   1.1.2.1          boolean done = false;
301 duncan   1.1.2.1          private Derivation derivation;
302 duncan   1.1.2.1          private TypeMap typeMap;
303 duncan   1.1.2.2  
304 duncan   1.1.2.1          Interpreter(StaticState ss, TreeStackFrame sf) {
305 duncan   1.1.2.1              this.ss = ss; this.sf = sf; 
306 duncan   1.1.2.2              while (sf.pc instanceof SEQ)
307 duncan   1.1.2.14                 sf.pc = ((SEQ)sf.pc).getLeft();
308 duncan   1.1.2.1          }
309 duncan   1.1.2.1  
310 duncan   1.1.2.2          void advance(int which_succ) {
311 duncan   1.1.2.14             // FIXME:  this needs to use the grapher interface. 
312 duncan   1.1.2.14             //Edge e = sf.pc.nextEdge(which_succ);
313 duncan   1.1.2.14             //sf.pc = (Stm)e.to();
314 duncan   1.1.2.1              ss.incrementInstructionCount();
315 duncan   1.1.2.1          }
316 duncan   1.1.2.1      }
317 duncan   1.1.2.1  
318 duncan   1.1.2.1      // The Tree interpreter
319 duncan   1.1.2.1      static private class TreeInterpreter extends Interpreter {
320 duncan   1.1.2.8          private Object[] params;
321 duncan   1.1.2.8          TreeInterpreter(StaticState ss, TreeStackFrame sf, Object[] params) {
322 duncan   1.1.2.1              super(ss, sf);
323 duncan   1.1.2.8              this.params = params;
324 duncan   1.1.2.1          }
325 duncan   1.1.2.1  
326 duncan   1.1.2.1          public void visit(Tree q) {
327 duncan   1.1.2.1              throw new Error("Hello? No defaults here.");
328 duncan   1.1.2.1          }
329 duncan   1.1.2.1          
330 duncan   1.1.2.1          public void visit(BINOP e) { 
331 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
332 duncan   1.1.2.2  
333 duncan   1.1.2.14             e.getLeft().accept(this);
334 duncan   1.1.2.14             e.getRight().accept(this);
335 duncan   1.1.2.1              
336 duncan   1.1.2.14             Object left  = sf.get(e.getLeft());
337 duncan   1.1.2.14             Object right = sf.get(e.getRight());
338 duncan   1.1.2.1  
339 duncan   1.1.2.1              // Case 1: neither operand is a Pointer object
340 duncan   1.1.2.1              if ((!(left instanceof Pointer)) &&
341 duncan   1.1.2.1                  (!(right instanceof Pointer))) {
342 duncan   1.1.2.1                  sf.update(e, BINOP.evalValue(e.getFactory(),
343 duncan   1.1.2.1                                               e.op, e.optype, 
344 duncan   1.1.2.1                                               left, right));
345 duncan   1.1.2.1  
346 duncan   1.1.2.1  
347 duncan   1.1.2.1              }
348 duncan   1.1.2.1              // Case 2: one or both operands is a Pointer object
349 duncan   1.1.2.1              else {
350 duncan   1.1.2.1                  if (e.op==Bop.CMPEQ) {
351 duncan   1.1.2.1                      if (left instanceof Pointer) { 
352 duncan   1.1.2.1                          sf.update(e, 
353 duncan   1.1.2.1                                    ((Pointer)left).equals(right)?
354 duncan   1.1.2.1                                    new Integer(1):
355 duncan   1.1.2.1                                    new Integer(0));
356 duncan   1.1.2.1                      }
357 duncan   1.1.2.1                      else {
358 bdemsky  1.1.2.4                          sf.update(e, new Integer(0));
359 bdemsky  1.1.2.4                      }
360 bdemsky  1.1.2.4                  }
361 bdemsky  1.1.2.4                  else if (e.op==Bop.CMPGT) { 
362 bdemsky  1.1.2.4                      if (left instanceof Pointer) { 
363 bdemsky  1.1.2.4                          Pointer leftPtr = (Pointer)left, rightPtr = (Pointer)right;
364 cananian 1.3.2.1                          assert leftPtr.getBase()==rightPtr.getBase();
365 bdemsky  1.1.2.4                          sf.update(e, 
366 bdemsky  1.1.2.4                                    (leftPtr.getOffset()>rightPtr.getOffset())?
367 bdemsky  1.1.2.4                                    new Integer(1):
368 bdemsky  1.1.2.4                                    new Integer(0));
369 bdemsky  1.1.2.4                      }
370 bdemsky  1.1.2.4                      else { 
371 duncan   1.1.2.1                          sf.update(e, new Integer(0));
372 duncan   1.1.2.1                      }
373 duncan   1.1.2.1                  }
374 duncan   1.1.2.1                  else if (e.op==Bop.ADD) {
375 duncan   1.1.2.1                      Pointer ptr; Object offset;
376 duncan   1.1.2.1  
377 duncan   1.1.2.1                      if (left instanceof Pointer) {
378 duncan   1.1.2.1                          // Both of them cannot be base pointers
379 cananian 1.3.2.1                          assert !(right instanceof Pointer);
380 duncan   1.1.2.1                          ptr = (Pointer)left;
381 duncan   1.1.2.1                          offset = right;
382 duncan   1.1.2.1                      }
383 duncan   1.1.2.1                      else { 
384 duncan   1.1.2.1                          ptr = (Pointer)right;
385 duncan   1.1.2.1                          offset = left;
386 duncan   1.1.2.1                      }
387 duncan   1.1.2.1                      
388 duncan   1.1.2.1                      if (Type.isDoubleWord(e.getFactory(), Type.POINTER)) 
389 duncan   1.1.2.1                          sf.update(e, ptr.add(((Long)offset).longValue()));
390 duncan   1.1.2.1                      else
391 duncan   1.1.2.1                          sf.update(e, ptr.add((long)((Integer)offset).intValue()));
392 duncan   1.1.2.1                  }
393 duncan   1.1.2.1                  else {
394 duncan   1.1.2.2                      if (DEBUG) db("*** ILLEGAL BINOP: " + 
395 duncan   1.1.2.2                                         e + ", " + left + ", " + right + 
396 duncan   1.1.2.2                                         " IN METHOD " + sf.getMethod());
397 duncan   1.1.2.1                      throw new Error
398 duncan   1.1.2.1                          ("Illegal opcode for Pointer object: " + e.op);
399 duncan   1.1.2.1                  }
400 duncan   1.1.2.1              }
401 duncan   1.1.2.1          }
402 duncan   1.1.2.1          
403 duncan   1.1.2.1          public void visit(CJUMP e) {
404 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
405 duncan   1.1.2.14             e.getTest().accept(this);
406 duncan   1.1.2.14             boolean b = (((Integer)sf.get(e.getTest())).intValue()!=0)?true:false;
407 duncan   1.1.2.2              if (b) advance(0);
408 duncan   1.1.2.2              else advance(1);
409 duncan   1.1.2.1          }
410 duncan   1.1.2.1          
411 duncan   1.1.2.1          public void visit(CONST e) { 
412 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
413 duncan   1.1.2.10             sf.update(e, e.value==null?(Number)new Integer(0):e.value);
414 duncan   1.1.2.1          }
415 duncan   1.1.2.9  
416 cananian 1.1.2.15         public void visit(DATUM e) { 
417 cananian 1.1.2.15             throw new Error("Should not have encountered a DATUM node");
418 duncan   1.1.2.9          }
419 duncan   1.1.2.1          
420 jwhaley  1.1.2.21         public void visit(EXPR e)  { 
421 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
422 duncan   1.1.2.1              // Execute e for side effects
423 duncan   1.1.2.14             e.getExp().accept(this);
424 duncan   1.1.2.2              advance(0);
425 duncan   1.1.2.1          }
426 duncan   1.1.2.1  
427 duncan   1.1.2.5          public void visit(NATIVECALL s) { 
428 cananian 1.3.2.1              assert isAllocation(s);  // Only native call we know about
429 duncan   1.1.2.8  
430 duncan   1.1.2.8              // Can't resolve ptr type yet
431 duncan   1.1.2.8              UndefinedPointer ptr=new UndefinedPointer(new UndefinedRef(ss), 0);
432 duncan   1.1.2.14             sf.update(((TEMP)s.getRetval()).temp, ptr);
433 duncan   1.1.2.8              advance(0);
434 duncan   1.1.2.5          }
435 duncan   1.1.2.5  
436 duncan   1.1.2.1          /* Let Method.invoke() distinguish between native and
437 duncan   1.1.2.1           * non-native methods */
438 duncan   1.1.2.5          public void visit(CALL s) { 
439 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + s);
440 duncan   1.1.2.5  
441 duncan   1.1.2.8              // FIXME: may want to allow other expressions than TEMPs
442 cananian 1.3.2.1              assert s.getRetval().kind()==TreeKind.TEMP;
443 cananian 1.3.2.1              assert s.getRetex().kind()==TreeKind.TEMP;
444 cananian 1.3.2.1              assert s.getHandler().kind()==TreeKind.NAME;
445 duncan   1.1.2.8  
446 duncan   1.1.2.14             s.getFunc().accept(this);
447 duncan   1.1.2.1  
448 duncan   1.1.2.8              // Dereference function ptr
449 duncan   1.1.2.8              HMethod method = 
450 duncan   1.1.2.14                 (HMethod)(((Pointer)sf.get(s.getFunc())).getValue());
451 duncan   1.1.2.14             ExpList  params    = s.getArgs(); 
452 duncan   1.1.2.8              Object[] oParams;
453 duncan   1.1.2.8              HClass[] paramTypes;
454 duncan   1.1.2.8              HClass[] pTypesTmp = method.getParameterTypes();
455 duncan   1.1.2.8              
456 duncan   1.1.2.8              if (!method.isStatic()) {
457 duncan   1.1.2.8                  // Add the extra "this" parameter
458 duncan   1.1.2.8                  paramTypes    = new HClass[pTypesTmp.length+1];
459 duncan   1.1.2.8                  paramTypes[0] = method.getDeclaringClass();
460 duncan   1.1.2.8                  System.arraycopy(pTypesTmp, 0, 
461 duncan   1.1.2.8                                   paramTypes, 1, pTypesTmp.length);
462 duncan   1.1.2.8              }
463 duncan   1.1.2.8              else { paramTypes = pTypesTmp; }
464 duncan   1.1.2.8  
465 duncan   1.1.2.8              oParams = new Object[paramTypes.length];
466 duncan   1.1.2.8              for (int i=0; params!=null; i++) {
467 duncan   1.1.2.8                  // Convert all parameters to native format, and store
468 duncan   1.1.2.8                  // in an array of objects
469 cananian 1.1.2.12                 params.head.accept(this);
470 duncan   1.1.2.8                  oParams[i] = 
471 duncan   1.1.2.8                      toNativeFormat(sf.get(params.head), paramTypes[i]);
472 duncan   1.1.2.8                  params = params.tail;
473 duncan   1.1.2.8              }
474 duncan   1.1.2.1                  
475 duncan   1.1.2.8              try {
476 duncan   1.1.2.8                  Object retval = invoke(ss, method, oParams);
477 duncan   1.1.2.8                  retval = retval==null?null:toNonNativeFormat(retval);
478 duncan   1.1.2.14                 sf.update(s.getRetval(), retval);
479 duncan   1.1.2.14                 sf.update(((TEMP)s.getRetval()).temp, retval);
480 duncan   1.1.2.8                  advance(0);  // Advance PC to normal branch
481 duncan   1.1.2.8              }
482 duncan   1.1.2.8              catch (InterpretedThrowable it) {
483 cananian 1.1.2.13                 // ignore handler param
484 duncan   1.1.2.14                 sf.update(s.getRetex(), new FieldPointer(it.ex, 0));
485 duncan   1.1.2.14                 sf.update(((TEMP)s.getRetex()).temp, sf.get(s.getRetex()));
486 duncan   1.1.2.8                  advance(1);  // Advance PC to exceptional branch
487 duncan   1.1.2.1              }
488 duncan   1.1.2.1          }
489 duncan   1.1.2.1  
490 duncan   1.1.2.1          public void visit(JUMP e) { 
491 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
492 cananian 1.3.2.1              assert e.getExp() instanceof NAME;
493 duncan   1.1.2.2              advance(0);
494 duncan   1.1.2.1          }
495 duncan   1.1.2.1            
496 duncan   1.1.2.1          public void visit(LABEL s) { 
497 duncan   1.1.2.2              if (DEBUG) db("Visiting LABEL: " + s);
498 duncan   1.1.2.1              /* Nothing to do here, just advance the PC */ 
499 duncan   1.1.2.2              advance(0);
500 duncan   1.1.2.1          }
501 duncan   1.1.2.1  
502 duncan   1.1.2.1          public void visit(MEM e) { 
503 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
504 duncan   1.1.2.14             e.getExp().accept(this);
505 duncan   1.1.2.2              Pointer ptr;
506 duncan   1.1.2.2  
507 duncan   1.1.2.14             if (DEBUG) db("Trying to derefence: " + e.getExp());
508 duncan   1.1.2.5              // Can only dereference Pointer types
509 duncan   1.1.2.14             ptr = (Pointer)sf.get(e.getExp());
510 duncan   1.1.2.2  
511 duncan   1.1.2.1              sf.update(e, ptr.getValue());
512 duncan   1.1.2.1          }
513 duncan   1.1.2.1  
514 duncan   1.1.2.8          public void visit(METHOD s) { 
515 duncan   1.1.2.8              if (DEBUG) db("Visiting: " + s);
516 duncan   1.1.2.8  
517 cananian 1.1.2.20             TEMP[] tParams = s.getParams();
518 duncan   1.1.2.8              for (int i=1; i<tParams.length; i++) {
519 duncan   1.1.2.8                  sf.update(tParams[i].temp, toNonNativeFormat(params[i-1]));
520 duncan   1.1.2.8              }
521 duncan   1.1.2.8              advance(0);
522 duncan   1.1.2.8          }
523 duncan   1.1.2.8  
524 duncan   1.1.2.8  
525 duncan   1.1.2.2          public void visit(MOVE s) {
526 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + s);
527 duncan   1.1.2.14             s.getSrc().accept(this);
528 duncan   1.1.2.14             Object srcValue = sf.get(s.getSrc());
529 duncan   1.1.2.1  
530 duncan   1.1.2.14             if (s.getDst() instanceof MEM) { 
531 duncan   1.1.2.14                 MEM location = (MEM)s.getDst();
532 duncan   1.1.2.14                 location.getExp().accept(this);
533 duncan   1.1.2.14                 Pointer ptr = (Pointer)sf.get(location.getExp());
534 duncan   1.1.2.1  
535 duncan   1.1.2.1                  try {
536 duncan   1.1.2.14                     ptr.updateValue(sf.get(s.getSrc()));
537 duncan   1.1.2.1                  }
538 duncan   1.1.2.1                  catch (PointerTypeChangedException e) {
539 duncan   1.1.2.3                      if (DEBUG) db("PTYPE resolved: " + ptr + " --> " + e.ptr);
540 duncan   1.1.2.1                      // The type of ptr has been resolved.  Update the
541 duncan   1.1.2.1                      // stack frame accordingly. 
542 duncan   1.1.2.1                      ptr = ptr.add(-ptr.getOffset());
543 duncan   1.1.2.1                      sf.replace(ptr, e.ptr);
544 duncan   1.1.2.1                      sf.replace(ptr.add(-1), e.ptr.add(-1));
545 duncan   1.1.2.1                      sf.replace(ptr.add(-2), e.ptr.add(-2));
546 duncan   1.1.2.1                      if (e.ptr instanceof ArrayPointer)
547 duncan   1.1.2.1                          sf.replace(ptr.add(-3), e.ptr.add(-3));
548 duncan   1.1.2.1                  }
549 duncan   1.1.2.1              }
550 duncan   1.1.2.14             else if (s.getDst() instanceof TEMP) { 
551 duncan   1.1.2.14                 TEMP dst = (TEMP)s.getDst();
552 duncan   1.1.2.14                 sf.update(dst.temp, sf.get(s.getSrc()));
553 duncan   1.1.2.14                 sf.update(dst, sf.get(s.getSrc()));  // maybe not necessary
554 duncan   1.1.2.1              }
555 duncan   1.1.2.1              else
556 duncan   1.1.2.2                  throw new Error("Bad type for destination in: " + s);
557 duncan   1.1.2.1  
558 duncan   1.1.2.2              advance(0);
559 duncan   1.1.2.1          }
560 duncan   1.1.2.1  
561 duncan   1.1.2.1          public void visit(NAME e) { 
562 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
563 duncan   1.1.2.11 
564 duncan   1.1.2.11             // Still pretty ugly, but more reliable than before
565 duncan   1.1.2.11             InterpreterOffsetMap map = 
566 cananian 1.1.2.17                 (InterpreterOffsetMap)
567 cananian 1.1.2.17                 ((DefaultFrame)e.getFactory().getFrame())
568 cananian 1.1.2.17                 .getOffsetMap();
569 duncan   1.1.2.11             if (map.stringConstantMap().containsValue(e.label)) { 
570 duncan   1.1.2.1                  sf.update(e, new StringPointer(ss, e.label));
571 duncan   1.1.2.1              }
572 duncan   1.1.2.1              else {
573 duncan   1.1.2.1                  sf.update(e, new ConstPointer(e.label, ss));
574 duncan   1.1.2.1              }
575 duncan   1.1.2.1          }
576 duncan   1.1.2.1  
577 duncan   1.1.2.1          public void visit(RETURN q) {
578 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + q);
579 duncan   1.1.2.14             q.getRetval().accept(this);
580 duncan   1.1.2.14             Tret = sf.get(q.getRetval());
581 duncan   1.1.2.1              done = true;
582 duncan   1.1.2.9          }
583 duncan   1.1.2.9  
584 duncan   1.1.2.9          public void visit(SEGMENT s) { 
585 duncan   1.1.2.9              advance(0);  // Don't use SEGMENT nodes in the interpreter
586 duncan   1.1.2.1          }
587 duncan   1.1.2.1  
588 duncan   1.1.2.1          public void visit(SEQ e) { 
589 duncan   1.1.2.2              throw new Error("Should not be visiting SEQ nodes");
590 duncan   1.1.2.1          }
591 duncan   1.1.2.1  
592 duncan   1.1.2.1  
593 duncan   1.1.2.1          public void visit(TEMP e) {
594 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
595 duncan   1.1.2.1              Object tmpValue = sf.get(e.temp);
596 duncan   1.1.2.1              if (tmpValue != null) 
597 duncan   1.1.2.1                  sf.update(e, tmpValue);
598 duncan   1.1.2.1          }
599 duncan   1.1.2.1              
600 duncan   1.1.2.1          public void visit(THROW e) { 
601 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
602 duncan   1.1.2.1              HClass type;
603 duncan   1.1.2.14             Pointer exc = (Pointer)sf.get(e.getRetex());
604 duncan   1.1.2.1              
605 duncan   1.1.2.1              // Make getType() abstract method in Pointer?
606 duncan   1.1.2.1              if (exc instanceof FieldPointer) {
607 duncan   1.1.2.1                  type = ((ObjectRef)exc.getBase()).type;
608 duncan   1.1.2.1              }
609 duncan   1.1.2.1              else if (exc instanceof ConstPointer) {
610 duncan   1.1.2.1                  type = ((ConstPointer)exc).getType();
611 duncan   1.1.2.1              }
612 duncan   1.1.2.1              else {
613 duncan   1.1.2.1                  throw new Error("BAD pointer type for throw: " + exc);
614 duncan   1.1.2.1              }
615 duncan   1.1.2.1  
616 duncan   1.1.2.14             e.getRetex().accept(this);
617 duncan   1.1.2.14             Texc = toNativeFormat(sf.get(e.getRetex()), type);
618 duncan   1.1.2.1              done = true;
619 duncan   1.1.2.1          }        
620 duncan   1.1.2.1          
621 duncan   1.1.2.1          public void visit(UNOP e) { 
622 duncan   1.1.2.2              if (DEBUG) db("Visiting: " + e);
623 duncan   1.1.2.14             e.getOperand().accept(this);
624 duncan   1.1.2.1  
625 duncan   1.1.2.14             Object operand  = sf.get(e.getOperand());
626 duncan   1.1.2.1  
627 duncan   1.1.2.1              if (operand instanceof Pointer) {
628 duncan   1.1.2.1                if (operand instanceof UndefinedPointer) {
629 duncan   1.1.2.1                  // dont convert undefinedpointers
630 duncan   1.1.2.1                  sf.update(e, e);
631 duncan   1.1.2.1                }
632 duncan   1.1.2.1                else {
633 duncan   1.1.2.2                  System.err.println("WARNING: dangerous pointer op!");
634 duncan   1.1.2.1                  sf.update(e, UNOP.evalValue(e.getFactory(), 
635 duncan   1.1.2.1                                              e.op, e.optype, 
636 duncan   1.1.2.1                                              ((Pointer)operand).getValue()));
637 duncan   1.1.2.1                }
638 duncan   1.1.2.1                
639 duncan   1.1.2.1              }
640 duncan   1.1.2.1              else {
641 duncan   1.1.2.1                  sf.update(e, UNOP.evalValue(e.getFactory(),
642 duncan   1.1.2.1                                              e.op, e.optype, 
643 duncan   1.1.2.1                                              operand));
644 duncan   1.1.2.1              }
645 duncan   1.1.2.1          }
646 duncan   1.1.2.1              
647 duncan   1.1.2.1          // Hack to determine if "i" is an allocation.  See 
648 duncan   1.1.2.1          // InterpreterAllocationStrategy.
649 duncan   1.1.2.1          private static boolean isAllocation(INVOCATION i) {
650 duncan   1.1.2.14             if (i.getFunc() instanceof NAME)
651 duncan   1.1.2.1                  return
652 duncan   1.1.2.14                     ((NAME)i.getFunc()).label.toString().equals("RUNTIME_MALLOC");
653 duncan   1.1.2.1              else return false; 
654 duncan   1.1.2.1          }
655 duncan   1.1.2.1      }
656 cananian 1.2      }