1 cananian 1.1.2.1 // TreeBuilder.java, created Sat Sep 25 07:23:21 1999 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Backend.RuntimeTiny; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Analysis.Maps.AllocationInformation.AllocationProperties; 8 cananian 1.1.2.1 import harpoon.Analysis.Maps.Derivation; 9 cananian 1.1.2.1 import harpoon.Backend.Maps.ClassDepthMap; 10 cananian 1.1.2.1 import harpoon.Backend.Maps.FieldMap; 11 cananian 1.1.2.1 import harpoon.Backend.Maps.MethodMap; 12 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 13 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 14 cananian 1.1.2.1 import harpoon.ClassFile.HField; 15 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 16 cananian 1.1.2.1 import harpoon.ClassFile.Linker; 17 cananian 1.1.2.1 import harpoon.IR.Tree.TreeFactory; 18 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 19 cananian 1.1.2.1 import harpoon.IR.Tree.Exp; 20 cananian 1.1.2.1 import harpoon.IR.Tree.ExpList; 21 cananian 1.1.2.1 import harpoon.IR.Tree.Bop; 22 cananian 1.1.2.1 import harpoon.IR.Tree.Uop; 23 cananian 1.1.2.1 import harpoon.IR.Tree.Translation; 24 cananian 1.1.2.1 import harpoon.IR.Tree.Type; 25 cananian 1.1.2.1 import harpoon.IR.Tree.BINOP; 26 cananian 1.1.2.1 import harpoon.IR.Tree.CALL; 27 cananian 1.1.2.1 import harpoon.IR.Tree.CJUMP; 28 cananian 1.1.2.1 import harpoon.IR.Tree.CONST; 29 cananian 1.1.2.1 import harpoon.IR.Tree.DATUM; 30 cananian 1.1.2.1 import harpoon.IR.Tree.DerivationGenerator; 31 cananian 1.1.2.1 import harpoon.IR.Tree.ESEQ; 32 cananian 1.1.2.1 import harpoon.IR.Tree.EXPR; 33 cananian 1.1.2.1 import harpoon.IR.Tree.INVOCATION; 34 cananian 1.1.2.1 import harpoon.IR.Tree.JUMP; 35 cananian 1.1.2.1 import harpoon.IR.Tree.LABEL; 36 cananian 1.1.2.1 import harpoon.IR.Tree.MEM; 37 cananian 1.1.2.1 import harpoon.IR.Tree.METHOD; 38 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE; 39 cananian 1.1.2.1 import harpoon.IR.Tree.NAME; 40 cananian 1.1.2.1 import harpoon.IR.Tree.NATIVECALL; 41 cananian 1.1.2.1 import harpoon.IR.Tree.OPER; 42 cananian 1.1.2.1 import harpoon.IR.Tree.RETURN; 43 cananian 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 44 cananian 1.1.2.1 import harpoon.IR.Tree.SEQ; 45 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP; 46 cananian 1.1.2.1 import harpoon.IR.Tree.THROW; 47 cananian 1.1.2.1 import harpoon.IR.Tree.UNOP; 48 cananian 1.1.2.1 import harpoon.Temp.Label; 49 cananian 1.1.2.1 import harpoon.Temp.Temp; 50 cananian 1.1.2.1 import harpoon.Util.HClassUtil; 51 cananian 1.1.2.1 import harpoon.Util.Util; 52 cananian 1.1.2.1 53 cananian 1.1.2.1 import harpoon.Backend.Runtime1.AllocationStrategy; 54 cananian 1.1.2.1 55 cananian 1.1.2.1 56 cananian 1.1.2.1 import java.util.HashSet; 57 cananian 1.1.2.1 import java.util.List; 58 cananian 1.1.2.1 import java.util.Set; 59 cananian 1.1.2.1 /** 60 cananian 1.1.2.1 * <code>RuntimeTiny.TreeBuilder</code> extends 61 cananian 1.1.2.1 * <code>Runtime1.TreeBuilder</code> to implement a more-compressed 62 cananian 1.1.2.1 * (but slower) object layout. 63 cananian 1.1.2.1 * 64 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 65 cananian 1.2 * @version $Id: TreeBuilder.java,v 1.2 2002/04/10 03:03:43 cananian Exp $ 66 cananian 1.1.2.1 */ 67 cananian 1.1.2.1 public class TreeBuilder extends harpoon.Backend.Runtime1.TreeBuilder { 68 cananian 1.1.2.5 final Runtime runtime; 69 cananian 1.1.2.1 70 cananian 1.1.2.1 protected TreeBuilder(Runtime runtime, 71 cananian 1.1.2.1 Linker linker, 72 cananian 1.1.2.1 AllocationStrategy as, boolean pointersAreLong) { 73 cananian 1.1.2.1 super(runtime, linker, as, pointersAreLong, 0/* hard-code ptr algn of zero*/); 74 cananian 1.1.2.1 this.runtime = runtime; 75 cananian 1.1.2.7 if (runtime.clazShrink) { 76 cananian 1.1.2.7 // adjust offsets, as claz is INT not POINTER now. 77 cananian 1.1.2.7 OBJECT_HEADER_SIZE-= (POINTER_SIZE - WORD_SIZE); 78 cananian 1.1.2.7 OBJ_HASH_OFF -= (POINTER_SIZE - WORD_SIZE); 79 cananian 1.1.2.7 OBJ_FZERO_OFF-= (POINTER_SIZE - WORD_SIZE); 80 cananian 1.1.2.7 OBJ_ALENGTH_OFF-=(POINTER_SIZE - WORD_SIZE); 81 cananian 1.1.2.7 OBJ_AZERO_OFF-= (POINTER_SIZE - WORD_SIZE); 82 cananian 1.1.2.7 } 83 cananian 1.1.2.7 if (runtime.hashlockShrink) { 84 cananian 1.1.2.7 // adjust offsets, as HASH field is no more. 85 cananian 1.1.2.7 OBJECT_HEADER_SIZE-= POINTER_SIZE; 86 cananian 1.1.2.7 OBJ_HASH_OFF -= POINTER_SIZE; 87 cananian 1.1.2.7 OBJ_FZERO_OFF-= POINTER_SIZE; 88 cananian 1.1.2.7 OBJ_ALENGTH_OFF-=POINTER_SIZE; 89 cananian 1.1.2.7 OBJ_AZERO_OFF-= POINTER_SIZE; 90 cananian 1.1.2.7 } 91 cananian 1.1.2.3 } 92 cananian 1.1.2.3 // byte-align all fields. 93 cananian 1.1.2.3 protected FieldMap initClassFieldMap() { 94 cananian 1.1.2.3 final FieldMap sfm = super.initClassFieldMap(); 95 cananian 1.1.2.5 final Runtime runtime = (Runtime) super.runtime; 96 cananian 1.1.2.3 if (!runtime.byteAlign) return sfm; 97 cananian 1.1.2.7 return new TinyPackedClassFieldMap(runtime) { 98 cananian 1.1.2.3 public int fieldSize(HField hf) { return sfm.fieldSize(hf); } 99 cananian 1.1.2.3 // conservative gc requires pointers to be aligned. 100 cananian 1.1.2.3 public int fieldAlignment(HField hf) { 101 cananian 1.1.2.7 // XXX HACK REMOVE ME 102 cananian 1.1.2.7 if (hf.getDeclaringClass().isArray() && 103 cananian 1.1.2.7 hf.getName().equals("length")) 104 cananian 1.1.2.7 return sfm.fieldAlignment(hf); // force array length to std loc 105 cananian 1.1.2.3 if (hf.getType().isPrimitive()) return 1; 106 cananian 1.1.2.4 return sfm.fieldAlignment(hf); 107 cananian 1.1.2.4 } 108 cananian 1.1.2.4 // "try hard" to align other types of fields. 109 cananian 1.1.2.4 public int fieldPreferredAlignment(HField hf) { 110 cananian 1.1.2.3 return sfm.fieldAlignment(hf); 111 cananian 1.1.2.3 } 112 cananian 1.1.2.3 }; 113 cananian 1.1.2.1 } 114 cananian 1.1.2.5 protected FieldMap getClassFieldMap() { return cfm; } 115 cananian 1.1.2.5 116 cananian 1.1.2.5 public int objectSize(HClass hc) { 117 cananian 1.1.2.5 int sz = super.objectSize(hc); 118 cananian 1.1.2.5 // because we can allocate fields at negative offsets, the 119 cananian 1.1.2.5 // superclass sometimes says we've got negative size! 120 cananian 1.1.2.5 // now, we know that ain't true: it just means that we need 121 cananian 1.1.2.5 // no fields past the header, i.e. that "non-header size"==0. 122 cananian 1.1.2.5 return (sz<0) ? 0 : sz; 123 cananian 1.1.2.5 } 124 cananian 1.1.2.1 125 cananian 1.1.2.1 // allocate 'length' bytes plus object header; fill in object header. 126 cananian 1.1.2.1 // shift return pointer appropriately for an object reference. 127 cananian 1.1.2.1 public Exp objAlloc(TreeFactory tf, HCodeElement source, 128 cananian 1.1.2.1 DerivationGenerator dg, 129 cananian 1.1.2.1 AllocationProperties ap, 130 cananian 1.1.2.1 HClass objectType, Exp length) { 131 cananian 1.1.2.2 if (!runtime.clazShrink) 132 cananian 1.1.2.2 return super.objAlloc(tf, source, dg, ap, objectType, length); 133 cananian 1.1.2.1 Temp Tobj = new Temp(tf.tempFactory(), "rt"); 134 cananian 1.1.2.1 // masked version of object pointer. 135 cananian 1.1.2.1 Temp Tmasked = new Temp(tf.tempFactory(), "rt"); 136 cananian 1.1.2.1 Derivation.DList maskedDL = new Derivation.DList(Tobj, true, null); 137 cananian 1.1.2.1 return new ESEQ 138 cananian 1.1.2.1 (tf, source, 139 cananian 1.1.2.1 new SEQ 140 cananian 1.1.2.1 (tf, source, 141 cananian 1.1.2.1 new MOVE // allocate memory; put pointer in Tobj. 142 cananian 1.1.2.1 (tf, source, 143 cananian 1.1.2.1 DECLARE(dg, objectType/*not an obj yet*/, Tobj, 144 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tobj)), 145 cananian 1.1.2.1 as.memAlloc 146 cananian 1.1.2.1 (tf, source, dg, ap, 147 cananian 1.1.2.1 new BINOP 148 cananian 1.1.2.1 (tf, source, Type.INT, Bop.ADD, 149 cananian 1.1.2.1 length, 150 cananian 1.1.2.1 new CONST(tf, source, OBJECT_HEADER_SIZE)))), 151 cananian 1.1.2.1 new SEQ 152 cananian 1.1.2.1 (tf, source, 153 cananian 1.1.2.1 new MOVE // save a masked version of the pointer. 154 cananian 1.1.2.1 (tf, source, 155 cananian 1.1.2.1 DECLARE(dg, maskedDL, 156 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tmasked)), 157 cananian 1.1.2.1 PTRMASK(tf, source, dg, 158 cananian 1.1.2.1 DECLARE(dg, objectType/*not an obj yet*/, Tobj, 159 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tobj)))), 160 cananian 1.1.2.1 new SEQ 161 cananian 1.1.2.1 (tf, source, 162 cananian 1.1.2.7 runtime.hashlockShrink ? (Stm) 163 cananian 1.1.2.7 // insert a NOP here if we're shrinking the hashlock. 164 cananian 1.1.2.7 new EXPR(tf, source, new CONST(tf, source, 0)) : (Stm) 165 cananian 1.1.2.1 new MOVE // assign the new object a hashcode. 166 cananian 1.1.2.1 (tf, source, 167 cananian 1.1.2.1 DECLARE(dg, HClass.Void/*hashcode, not an object*/, 168 cananian 1.1.2.1 new MEM 169 cananian 1.1.2.1 (tf, source, Type.POINTER, /* hashcode is pointer size */ 170 cananian 1.1.2.1 new BINOP 171 cananian 1.1.2.1 (tf, source, Type.POINTER, Bop.ADD, 172 cananian 1.1.2.1 DECLARE(dg, maskedDL, 173 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tmasked)), 174 cananian 1.1.2.1 new CONST(tf, source, OBJ_HASH_OFF)))), 175 cananian 1.1.2.1 new BINOP // set the low bit to indicate an uninflated object. 176 cananian 1.1.2.1 (tf, source, Type.POINTER, Bop.ADD, 177 cananian 1.1.2.1 DECLARE(dg, maskedDL, 178 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tmasked)), 179 cananian 1.1.2.1 new CONST(tf, source, 1))), 180 cananian 1.1.2.7 181 cananian 1.1.2.1 new MOVE // assign the new object a class *index*. 182 cananian 1.1.2.1 (tf, source, 183 cananian 1.1.2.1 new MEM 184 cananian 1.1.2.1 (tf, source, Type.INT, /* index, not pointer anymore */ 185 cananian 1.1.2.1 new BINOP 186 cananian 1.1.2.1 (tf, source, Type.POINTER, Bop.ADD, 187 cananian 1.1.2.1 DECLARE(dg, maskedDL, 188 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tmasked)), 189 cananian 1.1.2.1 new CONST(tf, source, OBJ_CLAZ_OFF))), 190 cananian 1.1.2.1 new CONST(tf, source, runtime.cn.clazNumber(objectType)))))), 191 cananian 1.1.2.1 // result of ESEQ is new object pointer 192 cananian 1.1.2.1 DECLARE(dg, objectType/*finally an obj*/, Tobj, 193 cananian 1.1.2.1 new TEMP(tf, source, Type.POINTER, Tobj))); 194 cananian 1.1.2.1 } 195 cananian 1.1.2.1 196 cananian 1.1.2.1 protected Exp _claz_(TreeFactory tf, HCodeElement source, 197 cananian 1.1.2.1 DerivationGenerator dg, 198 cananian 1.1.2.1 Translation.Exp objectref) { 199 cananian 1.1.2.1 if (!runtime.clazShrink) 200 cananian 1.1.2.1 return super._claz_(tf, source, dg, objectref); 201 cananian 1.1.2.1 // okay, load a compressed claz pointer, using the claz table. 202 cananian 1.1.2.1 Exp index_pointer = 203 cananian 1.1.2.1 new BINOP 204 cananian 1.1.2.1 (tf, source, Type.POINTER, Bop.ADD, 205 cananian 1.1.2.1 PTRMASK(tf, source, dg, objectref.unEx(tf)), 206 cananian 1.1.2.1 new CONST(tf, source, OBJ_CLAZ_OFF)); 207 cananian 1.1.2.5 int bitwidth=runtime.clazBytes * 8; 208 cananian 1.1.2.5 if (bitwidth>16) bitwidth=32; // XXX no 24-bit types 209 cananian 1.1.2.1 Exp index_value = 210 cananian 1.1.2.1 new MEM 211 cananian 1.1.2.5 (tf, source, bitwidth, false, 212 cananian 1.1.2.1 index_pointer); 213 cananian 1.1.2.1 // now look up index in claz table 214 cananian 1.1.2.1 Exp claz_pointer_pointer = 215 cananian 1.1.2.1 new BINOP 216 cananian 1.1.2.1 (tf, source, Type.POINTER, Bop.ADD, 217 cananian 1.1.2.1 new BINOP 218 cananian 1.1.2.1 (tf, source, Type.INT, Bop.MUL, 219 cananian 1.1.2.1 index_value, 220 cananian 1.1.2.1 new CONST(tf, source, POINTER_SIZE)), 221 cananian 1.1.2.1 new NAME 222 cananian 1.1.2.1 (tf, source, new Label 223 cananian 1.1.2.1 (runtime.getNameMap().c_function_name("FNI_claz_table")))); 224 cananian 1.1.2.1 return DECLARE(dg, HClass.Void/*claz pointer*/, 225 cananian 1.1.2.1 new MEM 226 cananian 1.1.2.1 (tf, source, Type.POINTER, claz_pointer_pointer)); 227 cananian 1.1.2.1 } 228 cananian 1.2 }