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 }