1 cananian 1.1.4.1 // ObjectBuilder.java, created Mon Oct 11 18:56:52 1999 by cananian 2 cananian 1.1.4.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.4.1 package harpoon.Backend.Runtime1; 5 cananian 1.1.4.1 6 cananian 1.1.4.1 import harpoon.Backend.Generic.Runtime.ObjectBuilder.Info; 7 cananian 1.1.4.1 import harpoon.Backend.Generic.Runtime.ObjectBuilder.ArrayInfo; 8 cananian 1.1.4.1 import harpoon.Backend.Generic.Runtime.ObjectBuilder.ObjectInfo; 9 cananian 1.1.4.1 import harpoon.Backend.Maps.FieldMap; 10 cananian 1.1.4.1 import harpoon.Backend.Maps.NameMap; 11 cananian 1.1.4.1 import harpoon.ClassFile.HClass; 12 cananian 1.1.4.1 import harpoon.ClassFile.HField; 13 cananian 1.1.4.1 import harpoon.IR.Tree.Exp; 14 cananian 1.1.4.1 import harpoon.IR.Tree.Stm; 15 cananian 1.1.4.1 import harpoon.IR.Tree.TreeFactory; 16 cananian 1.1.4.2 import harpoon.IR.Tree.ALIGN; 17 cananian 1.1.4.1 import harpoon.IR.Tree.CONST; 18 cananian 1.1.4.4 import harpoon.IR.Tree.DATUM; 19 cananian 1.1.4.1 import harpoon.IR.Tree.LABEL; 20 cananian 1.1.4.1 import harpoon.IR.Tree.NAME; 21 cananian 1.1.4.1 import harpoon.IR.Tree.SEGMENT; 22 cananian 1.1.4.1 import harpoon.Temp.Label; 23 cananian 1.1.4.10 import harpoon.Util.ArrayIterator; 24 cananian 1.1.4.1 import harpoon.Util.Util; 25 cananian 1.1.4.1 26 cananian 1.1.4.1 import java.util.ArrayList; 27 cananian 1.3.2.4 import java.util.Collections; 28 cananian 1.1.4.1 import java.util.Iterator; 29 cananian 1.1.4.1 import java.util.List; 30 cananian 1.1.4.5 import java.util.Random; 31 cananian 1.1.4.1 /** 32 cananian 1.1.4.1 * <code>ObjectBuilder</code> is an implementation of 33 cananian 1.1.4.1 * <code>harpoon.Backend.Generic.Runtime.ObjectBuilder</code> for the 34 cananian 1.1.4.1 * <code>Runtime1</code> runtime. 35 cananian 1.1.4.10 * <p> 36 cananian 1.1.4.10 * To accomodate transformations which add fields to 37 cananian 1.1.4.10 * <code>java.lang.Object</code>, this 38 cananian 1.1.4.10 * <code>Runtime.ObjectBuilder</code> initializes all fields of 39 cananian 1.1.4.10 * <code>Object</code> with <code>null</code>, rather than attempting 40 cananian 1.1.4.10 * to consult the given <code>Info</code> for them. If other behavior 41 cananian 1.1.4.10 * is eventually needed, it is a custom <code>RootOracle</code> be 42 cananian 1.1.4.10 * defined and provided to the constructor which will be consulted on 43 cananian 1.1.4.10 * the value of every field *before* any <code>Info</code>. 44 cananian 1.1.4.10 * This provides for extensibility without direct code modifications 45 cananian 1.1.4.10 * to the various parts of <code>Runtime1</code> which use this 46 cananian 1.1.4.10 * <code>ObjectBuilder</code>. 47 cananian 1.1.4.1 * 48 cananian 1.1.4.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 49 cananian 1.8 * @version $Id: ObjectBuilder.java,v 1.8 2004/02/08 03:20:58 cananian Exp $ 50 cananian 1.1.4.1 */ 51 cananian 1.1.4.1 public class ObjectBuilder 52 cananian 1.1.4.1 extends harpoon.Backend.Generic.Runtime.ObjectBuilder { 53 cananian 1.3.2.2 protected final Runtime runtime; 54 cananian 1.3.2.2 protected final boolean pointersAreLong; 55 cananian 1.3.2.2 protected final RootOracle ro; 56 cananian 1.3.2.2 protected final Random rnd; 57 cananian 1.3.2.2 protected final HClass HCobject; // cache HClass for java.lang.Object 58 cananian 1.1.4.1 59 cananian 1.1.4.10 /** Creates a <code>ObjectBuilder</code> with a <code>RootOracle</code> 60 cananian 1.1.4.10 * which supplies <code>null</code> values to any field of 61 cananian 1.1.4.10 * <code>java.lang.Object</code> (which there usually aren't any of). 62 cananian 1.1.4.10 */ 63 cananian 1.1.4.1 public ObjectBuilder(Runtime runtime) { 64 cananian 1.1.4.10 this(runtime, new RootOracle() { 65 bdemsky 1.1.4.16 public long counter=1; 66 cananian 1.1.4.10 public Object get(HField hf, Info addlinfo) { 67 cananian 1.1.4.10 if (hf.getDeclaringClass().getName().equals("java.lang.Object")) 68 bdemsky 1.1.4.16 if (hf.getName().equals("UID")) { 69 bdemsky 1.1.4.16 System.out.println("NI: "+addlinfo.type().getName().replace('.','/')+" "+(counter)); 70 bdemsky 1.1.4.16 return new Long(counter++); 71 bdemsky 1.1.4.16 } 72 bdemsky 1.1.4.16 else 73 bdemsky 1.1.4.16 return defaultValue(hf);// fields of Object initialized to 0 74 cananian 1.1.4.10 else return NOT_A_VALUE; 75 cananian 1.1.4.10 } 76 cananian 1.1.4.10 }); 77 cananian 1.1.4.10 } 78 cananian 1.1.4.10 /** Creates a <code>ObjectBuilder</code>. */ 79 cananian 1.1.4.10 public ObjectBuilder(Runtime runtime, RootOracle ro) { 80 cananian 1.1.4.15 this.runtime = runtime; 81 cananian 1.1.4.5 this.pointersAreLong = runtime.frame.pointersAreLong(); 82 cananian 1.1.4.10 this.ro = ro; 83 cananian 1.1.4.17 this.rnd = new Random(1234/*runtime.frame.hashCode()*/);//repeatable? 84 cananian 1.1.4.10 this.HCobject = runtime.frame.getLinker().forName("java.lang.Object"); 85 cananian 1.1.4.1 } 86 cananian 1.1.4.1 87 cananian 1.1.4.1 public Stm buildObject(TreeFactory tf, ObjectInfo info, 88 cananian 1.1.4.1 boolean exported) { 89 cananian 1.1.4.15 FieldMap cfm = ((TreeBuilder) runtime.getTreeBuilder()).cfm; 90 cananian 1.3.2.1 assert !info.type().isArray(); 91 cananian 1.3.2.1 assert !info.type().isPrimitive(); 92 cananian 1.3.2.3 List<Stm> stmlist = new ArrayList<Stm>(); 93 cananian 1.1.4.1 // header 94 cananian 1.1.4.1 stmlist.add(makeHeader(tf, info, exported)); 95 cananian 1.3.2.5 int startOffset = headerFinalOffset(info); 96 cananian 1.1.4.1 // fields, in field order 97 cananian 1.3.2.3 List<HField> l = cfm.fieldList(info.type()); 98 cananian 1.3.2.5 int endOffset = (l.size()==0) ? startOffset : 99 cananian 1.3.2.4 cfm.fieldOffset(l.get(l.size()-1))+cfm.fieldSize(l.get(l.size()-1)); 100 cananian 1.3.2.5 Stm s = makeFields(tf, info, l, startOffset, endOffset); 101 cananian 1.3.2.4 if (s!=null) stmlist.add(s); 102 cananian 1.1.4.1 // done -- ta da! 103 cananian 1.1.4.1 return Stm.toStm(stmlist); 104 cananian 1.1.4.1 } 105 cananian 1.1.4.1 public Stm buildArray(TreeFactory tf, ArrayInfo info, 106 cananian 1.1.4.1 boolean exported) { 107 cananian 1.1.4.15 FieldMap cfm = ((TreeBuilder) runtime.getTreeBuilder()).cfm; 108 cananian 1.3.2.1 assert info.type().isArray(); 109 cananian 1.1.4.1 HClass cType = info.type().getComponentType(); 110 cananian 1.3.2.3 List<Stm> stmlist = new ArrayList<Stm>(info.length()+2); 111 cananian 1.1.4.1 // header 112 cananian 1.1.4.1 stmlist.add(makeHeader(tf, info, exported)); 113 cananian 1.3.2.5 int startOffset = headerFinalOffset(info); 114 cananian 1.3.2.5 // fields of the object, including the length field. in order. 115 cananian 1.3.2.5 List<HField> l = cfm.fieldList(info.type()); 116 cananian 1.3.2.5 assert l.size() > 0; // always at least the length field! 117 cananian 1.3.2.5 int endOffset = 118 cananian 1.3.2.4 cfm.fieldOffset(l.get(l.size()-1))+cfm.fieldSize(l.get(l.size()-1)); 119 cananian 1.7 // always pad to pointer-size. 120 cananian 1.7 while (0 != (endOffset % (pointersAreLong?8:4))) 121 cananian 1.7 endOffset++; // not the most efficient calculation, but readable. 122 cananian 1.3.2.5 Stm s = makeFields(tf, info, l, startOffset, endOffset); 123 cananian 1.3.2.5 assert s!=null; // always the length! 124 cananian 1.3.2.5 stmlist.add(s); 125 cananian 1.1.4.1 // data 126 cananian 1.1.4.1 for (int i=0; i<info.length(); i++) 127 cananian 1.1.4.1 stmlist.add(makeDatum(tf, info.get(i))); 128 cananian 1.1.4.1 // done -- ta da! 129 cananian 1.1.4.1 return Stm.toStm(stmlist); 130 cananian 1.1.4.1 } 131 cananian 1.3.2.4 private Object lookup(Info info, HField hf) { 132 cananian 1.1.4.10 Object o = ro.get(hf, info); 133 cananian 1.3.2.4 if (o != ro.NOT_A_VALUE) return o; 134 cananian 1.3.2.5 if (info instanceof ArrayInfo && hf.getName().equals("length")) 135 cananian 1.3.2.5 // XXX should wrap more precisely based on hf.getType(). 136 cananian 1.3.2.5 // (arrays may have small length fields in future) 137 cananian 1.3.2.5 return new Integer(((ArrayInfo)info).length()); 138 cananian 1.3.2.5 assert info instanceof ObjectInfo : 139 cananian 1.3.2.5 "field of array not given a value: "+hf+" / "+info; 140 cananian 1.3.2.4 return ((ObjectInfo)info).get(hf); 141 cananian 1.1.4.10 } 142 cananian 1.3.2.2 protected Stm makeHeader(TreeFactory tf, Info info, boolean exported) 143 cananian 1.1.4.1 { 144 cananian 1.3.2.3 List<Stm> stmlist = new ArrayList<Stm>(4); 145 cananian 1.6 // align to word boundary (double-word on 64-bit platforms) 146 cananian 1.6 stmlist.add(new ALIGN(tf, null, pointersAreLong ? 8 : 4)); 147 cananian 1.1.4.1 // label: 148 cananian 1.1.4.1 stmlist.add(new LABEL(tf, null, info.label(), exported)); 149 cananian 1.1.4.1 // claz pointer 150 cananian 1.1.4.15 stmlist.add(_DATUM(tf, runtime.getNameMap().label(info.type()))); 151 cananian 1.1.4.3 // hash code. 152 cananian 1.1.4.5 // this is of pointer size, and must have the low bit set. we *could* 153 cananian 1.1.4.5 // emit a symbolic reference to info.label()+1 or some such, but 154 cananian 1.1.4.5 // this would complicate the pattern-matching instruction selector. 155 cananian 1.1.4.5 // so instead we'll just select a random number of the right length 156 cananian 1.1.4.5 // and set the low bit. 157 cananian 1.1.4.5 stmlist.add(makeDatum(tf, pointersAreLong ? 158 cananian 1.1.4.5 (Number) new Long(1 | rnd.nextLong()) : 159 cananian 1.1.4.5 (Number) new Integer(1 | rnd.nextInt()))); 160 cananian 1.1.4.1 // okay, done with header. 161 cananian 1.3.2.4 return Stm.toStm(stmlist); 162 cananian 1.3.2.4 } 163 cananian 1.3.2.5 protected int headerFinalOffset(Info info) { return 0; } 164 cananian 1.3.2.4 protected Stm makeFields(TreeFactory tf, Info info, List<HField> fields, 165 cananian 1.3.2.4 int startOffset, int endOffset) { 166 cananian 1.3.2.4 assert endOffset >= startOffset; 167 cananian 1.3.2.4 FieldMap cfm = ((TreeBuilder) runtime.getTreeBuilder()).cfm; 168 cananian 1.3.2.4 List<Stm> stmlist = new ArrayList<Stm>(2*fields.size()); 169 cananian 1.3.2.4 int offset = startOffset; 170 cananian 1.8 for (HField hf : fields) { 171 cananian 1.3.2.4 int thisOffset = cfm.fieldOffset(hf); 172 cananian 1.3.2.4 if (thisOffset<startOffset) continue; // ignore 173 cananian 1.3.2.4 if (thisOffset>endOffset) break; // done. 174 cananian 1.3.2.4 assert thisOffset >= offset : "fields in order"; 175 cananian 1.3.2.4 if (thisOffset > offset) // handle padding 176 cananian 1.3.2.4 stmlist.add(makePadding(tf, thisOffset-offset)); 177 cananian 1.3.2.4 stmlist.add(makeDatum(tf, lookup(info, hf))); 178 cananian 1.3.2.4 offset = thisOffset+cfm.fieldSize(hf); 179 cananian 1.3.2.4 } 180 cananian 1.3.2.4 // final padding, if needed. 181 cananian 1.3.2.4 if (endOffset > offset) 182 cananian 1.3.2.4 stmlist.add(makePadding(tf, endOffset-offset)); 183 cananian 1.3.2.4 // done -- ta da! 184 cananian 1.3.2.4 return Stm.toStm(stmlist); // MAY RETURN NULL. 185 cananian 1.3.2.4 } 186 cananian 1.3.2.4 Stm makePadding(TreeFactory tf, int bytes) { 187 cananian 1.3.2.4 List<Stm> stmlist = new ArrayList<Stm>(); 188 cananian 1.3.2.4 while (bytes > 0) 189 cananian 1.3.2.4 if (bytes>=8) { 190 cananian 1.3.2.4 stmlist.add(_DATUM(tf, new CONST(tf, null, (long)0))); 191 cananian 1.3.2.4 bytes-=8; 192 cananian 1.3.2.4 } else if (bytes>=4) { 193 cananian 1.3.2.4 stmlist.add(_DATUM(tf, new CONST(tf, null, (int)0))); 194 cananian 1.3.2.4 bytes-=4; 195 cananian 1.3.2.4 } else if (bytes>=2) { 196 cananian 1.3.2.4 stmlist.add(_DATUM(tf, new CONST(tf, null, 16, false, 0))); 197 cananian 1.3.2.4 bytes-=2; 198 cananian 1.3.2.4 } else { 199 cananian 1.3.2.4 stmlist.add(_DATUM(tf, new CONST(tf, null, 8, false, 0))); 200 cananian 1.3.2.4 bytes-=1; 201 cananian 1.3.2.4 } 202 cananian 1.3.2.4 // small-to-big 203 cananian 1.3.2.4 Collections.reverse(stmlist); 204 cananian 1.3.2.4 // done! 205 cananian 1.1.4.1 return Stm.toStm(stmlist); 206 cananian 1.1.4.1 } 207 cananian 1.1.4.1 Stm makeDatum(TreeFactory tf, Object datum) { 208 cananian 1.1.4.7 if (datum==null) 209 cananian 1.1.4.7 return _DATUM(tf, new CONST(tf, null)); // null constant. 210 cananian 1.1.4.7 else if (datum instanceof Integer) 211 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 212 cananian 1.1.4.1 ((Integer)datum).intValue())); 213 cananian 1.1.4.1 else if (datum instanceof Long) 214 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 215 cananian 1.1.4.1 ((Long)datum).longValue())); 216 cananian 1.1.4.1 else if (datum instanceof Float) 217 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 218 cananian 1.1.4.1 ((Float)datum).floatValue())); 219 cananian 1.1.4.1 else if (datum instanceof Double) 220 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 221 cananian 1.1.4.1 ((Double)datum).doubleValue())); 222 cananian 1.1.4.1 else if (datum instanceof Boolean) 223 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 8, false, 224 cananian 1.1.4.1 ((Boolean)datum).booleanValue()?1:0)); 225 cananian 1.1.4.1 else if (datum instanceof Byte) 226 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null, 8, true, 227 cananian 1.1.4.1 ((Byte)datum).intValue())); 228 cananian 1.1.4.1 else if (datum instanceof Short) 229 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null,16, true, 230 cananian 1.1.4.1 ((Short)datum).intValue())); 231 cananian 1.1.4.1 else if (datum instanceof Character) 232 cananian 1.1.4.4 return _DATUM(tf, new CONST(tf, null,16, false, 233 cananian 1.1.4.1 ((Character)datum).charValue())); 234 cananian 1.1.4.1 else if (datum instanceof Info) 235 cananian 1.1.4.4 return _DATUM(tf, ((Info)datum).label()); 236 cananian 1.1.4.4 else throw new Error("ILLEGAL DATUM TYPE"); 237 cananian 1.1.4.1 } 238 cananian 1.1.4.4 DATUM _DATUM(TreeFactory tf, Exp e) { 239 cananian 1.1.4.4 return new DATUM(tf, null, e); 240 cananian 1.1.4.1 } 241 cananian 1.1.4.4 DATUM _DATUM(TreeFactory tf, Label l) { 242 cananian 1.1.4.4 return new DATUM(tf,null,new NAME(tf,null,l)); 243 bdemsky 1.1.4.12 } 244 bdemsky 1.1.4.12 245 bdemsky 1.1.4.12 /** utility function copied from Interpret/Quads/Ref.java */ 246 bdemsky 1.1.4.12 static final Object defaultValue(HField f) { 247 bdemsky 1.1.4.12 if (f.isConstant()) return f.getConstant(); 248 bdemsky 1.1.4.12 return defaultValue(f.getType()); 249 bdemsky 1.1.4.12 } 250 bdemsky 1.1.4.12 static final Object defaultValue(HClass ty) { 251 bdemsky 1.1.4.12 if (!ty.isPrimitive()) return null; 252 bdemsky 1.1.4.12 if (ty == HClass.Boolean) return new Boolean(false); 253 bdemsky 1.1.4.12 if (ty == HClass.Byte) return new Byte((byte)0); 254 bdemsky 1.1.4.12 if (ty == HClass.Char) return new Character((char)0); 255 bdemsky 1.1.4.12 if (ty == HClass.Double) return new Double(0); 256 bdemsky 1.1.4.12 if (ty == HClass.Float) return new Float(0); 257 bdemsky 1.1.4.12 if (ty == HClass.Int) return new Integer(0); 258 bdemsky 1.1.4.12 if (ty == HClass.Long) return new Long(0); 259 bdemsky 1.1.4.12 if (ty == HClass.Short) return new Short((short)0); 260 bdemsky 1.1.4.12 throw new Error("Ack! What kinda default value is this?!"); 261 cananian 1.1.4.10 } 262 cananian 1.1.4.10 263 cananian 1.1.4.10 264 cananian 1.1.4.10 /** A <code>RootOracle</code> allows a transformation to add 265 cananian 1.1.4.10 * fields to <code>java.lang.Object</code> (or any other 266 cananian 1.1.4.10 * class, really) and provide the initial values for that 267 cananian 1.1.4.10 * field in the various runtime constant objects without 268 cananian 1.1.4.10 * having to directly extend every <code>ObjectInfo</code> 269 cananian 1.1.4.10 * used in this <code>Generic.Runtime</code> implementation. 270 cananian 1.1.4.10 * The <code>RootOracle</code> will be consulted for the 271 cananian 1.1.4.10 * value of every field *before* the <code>ObjectInfo</code>, 272 cananian 1.1.4.10 * allowing an override -- if no override is desired, the 273 cananian 1.1.4.10 * <code>RootOracle.get()</code> method should return 274 cananian 1.1.4.10 * <code>NOT_A_VALUE</code>. 275 cananian 1.1.4.10 */ 276 salcianu 1.5 public static abstract class RootOracle implements java.io.Serializable { 277 cananian 1.1.4.10 /** This is the constant value returned which this 278 cananian 1.1.4.10 * oracle doesn't wish to override the given field. */ 279 cananian 1.1.4.10 public static final Object NOT_A_VALUE = new Object(); 280 cananian 1.1.4.10 /** Returns the override value of the given field <code>hf</code> 281 cananian 1.1.4.10 * (more information about the object in question is 282 cananian 1.1.4.10 * provided by <code>addlinfo</code>); if this 283 cananian 1.1.4.10 * <code>RootOracle</code> doesn't wish to override this 284 cananian 1.1.4.10 * field, it should return the constant <code>NOT_A_VALUE</code>. 285 cananian 1.1.4.10 */ 286 cananian 1.1.4.10 public abstract Object get(HField hf, Info addlinfo); 287 cananian 1.1.4.1 } 288 cananian 1.2 }