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.Runtime1;
   5 cananian 1.1.2.1  
   6 cananian 1.1.2.3  import harpoon.Analysis.ClassHierarchy;
   7 cananian 1.1.2.25 import harpoon.Analysis.Maps.AllocationInformation.AllocationProperties;
   8 cananian 1.1.2.20 import harpoon.Analysis.Maps.Derivation;
   9 cananian 1.1.2.1  import harpoon.Backend.Maps.ClassDepthMap;
  10 cananian 1.1.2.3  import harpoon.Backend.Maps.FieldMap;
  11 cananian 1.1.2.3  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.3  import harpoon.ClassFile.HField;
  15 cananian 1.1.2.3  import harpoon.ClassFile.HMethod;
  16 cananian 1.1.2.20 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.9  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.3  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.13 import harpoon.IR.Tree.DATUM;
  30 cananian 1.1.2.20 import harpoon.IR.Tree.DerivationGenerator;
  31 cananian 1.1.2.1  import harpoon.IR.Tree.ESEQ;
  32 jwhaley  1.1.2.22 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.29 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.52 import java.util.ArrayList;
  54 cananian 1.1.2.3  import java.util.HashSet;
  55 cananian 1.1.2.3  import java.util.List;
  56 cananian 1.1.2.3  import java.util.Set;
  57 cananian 1.1.2.1  /**
  58 cananian 1.1.2.1   * <code>Runtime1.TreeBuilder</code> is an implementation of
  59 cananian 1.1.2.1   * <code>Generic.Runtime.TreeBuilder</code> which creates
  60 cananian 1.1.2.1   * accessor expressions for the <code>Runtime1</code> runtime.
  61 cananian 1.1.2.1   * <p>Pretty straightforward.  No weird hacks.
  62 cananian 1.1.2.1   * 
  63 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
  64 cananian 1.8       * @version $Id: TreeBuilder.java,v 1.8 2003/10/21 00:41:08 cananian Exp $
  65 cananian 1.1.2.1   */
  66 cananian 1.1.2.1  public class TreeBuilder extends harpoon.Backend.Generic.Runtime.TreeBuilder {
  67 cananian 1.1.2.41     // turning on this option means that no calls to synchronization primitives
  68 cananian 1.1.2.41     // will be generated.  this will obviously impair correctness if such
  69 cananian 1.1.2.41     // primitives are actually needed by the program, but allows us to
  70 cananian 1.1.2.41     // make a quick-and-dirty benchmark of the maximum-possible performance
  71 cananian 1.1.2.41     // improvement due to synchronization optimizations.
  72 cananian 1.1.2.50     private static final boolean noSync =
  73 cananian 1.1.2.41         Boolean.getBoolean("harpoon.runtime1.nosync");
  74 cananian 1.1.2.50     /* turning this on means that no alignment to boundaries larger than
  75 cananian 1.1.2.50      * a single word will be done.  This is sufficient on some architectures.
  76 cananian 1.1.2.50      */
  77 cananian 1.1.2.50     private static final boolean singleWordAlign =
  78 cananian 1.1.2.50         Boolean.getBoolean("harpoon.runtime1.single-word-align");
  79 cananian 1.1.2.41 
  80 cananian 1.3.2.3      /** allocation strategy to use. */
  81 cananian 1.3.2.3      protected final AllocationStrategy as;
  82 cananian 1.1.2.5  
  83 cananian 1.1.2.3      // integer constant sizes:
  84 cananian 1.1.2.31     protected final int WORD_SIZE;
  85 cananian 1.1.2.31     protected final int LONG_WORD_SIZE;
  86 bdemsky  1.1.2.30     protected final int POINTER_SIZE;
  87 cananian 1.3.2.6      protected       int OBJECT_HEADER_SIZE;
  88 cananian 1.1.2.3      // integer constant offsets:
  89 cananian 1.1.2.1      // layout of oobj
  90 cananian 1.3.2.6      protected       int OBJ_CLAZ_OFF;
  91 cananian 1.3.2.6      protected       int OBJ_HASH_OFF;
  92 cananian 1.3.2.6      protected       int OBJ_ALENGTH_OFF;
  93 cananian 1.3.2.6      protected       int OBJ_AZERO_OFF;
  94 cananian 1.3.2.6      protected       int OBJ_FZERO_OFF;
  95 cananian 1.1.2.1      // layout of claz
  96 cananian 1.1.2.31     protected final int CLAZ_INTERFACES_OFF;
  97 cananian 1.1.2.31     protected final int CLAZ_CLAZINFO;
  98 cananian 1.1.2.31     protected final int CLAZ_COMPONENT_OFF;
  99 cananian 1.1.2.31     protected final int CLAZ_INTERFZ_OFF;
 100 cananian 1.1.2.31     protected final int CLAZ_SIZE_OFF;
 101 cananian 1.8          protected final int CLAZ_DEPTH_OFF;
 102 cananian 1.1.2.31     protected final int CLAZ_GCENTRY_OFF;
 103 cananian 1.3.2.4      protected final int CLAZ_EXTRAINFO_OFF;
 104 cananian 1.1.2.31     protected final int CLAZ_DISPLAY_OFF;
 105 cananian 1.1.2.48     protected       int CLAZ_METHODS_OFF;
 106 cananian 1.1.2.3      
 107 cananian 1.1.2.3      // helper maps.
 108 cananian 1.1.2.31     protected final Runtime runtime;
 109 cananian 1.1.2.31     protected final Linker linker;
 110 cananian 1.1.2.48     protected       ClassDepthMap cdm;
 111 cananian 1.1.2.48     protected       MethodMap imm;
 112 cananian 1.1.2.31     protected final MethodMap cmm;
 113 cananian 1.1.2.31     protected final FieldMap  cfm;
 114 cananian 1.1.2.1  
 115 cananian 1.1.2.3      // set of string references made
 116 cananian 1.3.2.2      final Set<String> stringSet = new HashSet<String>();
 117 cananian 1.1.2.3  
 118 cananian 1.1.2.42     // if non-zero, then all pointer values are masked before
 119 cananian 1.1.2.42     // dereference.  this allows us to stuff additional information
 120 cananian 1.1.2.42     // into the low bits of the pointer. the value specifies the
 121 cananian 1.1.2.42     // alignment of all object pointers; thus how many bits we
 122 cananian 1.1.2.42     // should/may mask.
 123 cananian 1.1.2.42     private final int pointerAlignment;
 124 cananian 1.1.2.42 
 125 cananian 1.1.2.42     // pointerAlignment==0 means don't mask pointers.
 126 cananian 1.1.2.48     protected TreeBuilder(Runtime runtime, Linker linker,
 127 cananian 1.1.2.42                           AllocationStrategy as, boolean pointersAreLong,
 128 cananian 1.1.2.42                           int pointerAlignment) {
 129 cananian 1.1.2.42         this.pointerAlignment = pointerAlignment;
 130 cananian 1.1.2.3          this.runtime = runtime;
 131 cananian 1.1.2.20         this.linker = linker;
 132 cananian 1.1.2.5          this.as  = as;
 133 cananian 1.1.2.3          this.cmm = new harpoon.Backend.Analysis.ClassMethodMap();
 134 cananian 1.3.2.5          this.cfm = initClassFieldMap();
 135 cananian 1.1.2.3          // ----------    INITIALIZE SIZES AND OFFSETS    -----------
 136 cananian 1.1.2.3          WORD_SIZE = 4; // at least 32 bits.
 137 cananian 1.1.2.3          LONG_WORD_SIZE = 8; // at least 64 bits.
 138 cananian 1.1.2.3          POINTER_SIZE = pointersAreLong ? LONG_WORD_SIZE : WORD_SIZE;
 139 cananian 1.1.2.3  
 140 cananian 1.1.2.26         OBJECT_HEADER_SIZE = 2 * POINTER_SIZE;
 141 cananian 1.1.2.3          // layout of oobj
 142 cananian 1.1.2.24         // (note that the hashcode is actually pointer size, because it is
 143 cananian 1.1.2.24         //  used to point to an inflated_oobj structure after inflation)
 144 cananian 1.1.2.3          OBJ_CLAZ_OFF    = 0 * POINTER_SIZE;
 145 cananian 1.1.2.12         OBJ_HASH_OFF    = OBJ_CLAZ_OFF + 1 * POINTER_SIZE;
 146 cananian 1.1.2.24         OBJ_FZERO_OFF   = OBJ_HASH_OFF + 1 * POINTER_SIZE;
 147 cananian 1.1.2.34         OBJ_ALENGTH_OFF = OBJ_FZERO_OFF +
 148 cananian 1.1.2.34             // add (non-header) size of java.lang.Object, since arrays
 149 cananian 1.1.2.34             // inherit from it (allows us to add fields to Object)
 150 cananian 1.1.2.34             objectSize(linker.forName("java.lang.Object"));
 151 cananian 1.8              // ALENGTH is just a word-sized field, but we allocate POINTER_SIZE
 152 cananian 1.8              // to it in order to ensure that array elements are pointer-aligned
 153 cananian 1.8              // on 64-bit platforms.
 154 cananian 1.8              OBJ_AZERO_OFF   = OBJ_ALENGTH_OFF + 1 * POINTER_SIZE;
 155 cananian 1.1.2.3          // layout of claz
 156 cananian 1.1.2.3          CLAZ_INTERFACES_OFF = -1 * POINTER_SIZE;
 157 cananian 1.1.2.3          CLAZ_CLAZINFO    = 0 * POINTER_SIZE;
 158 cananian 1.1.2.3          CLAZ_COMPONENT_OFF=1 * POINTER_SIZE;
 159 cananian 1.1.2.3          CLAZ_INTERFZ_OFF = 2 * POINTER_SIZE;
 160 cananian 1.1.2.7          CLAZ_SIZE_OFF    = 3 * POINTER_SIZE;
 161 cananian 1.8              CLAZ_DEPTH_OFF   = 3 * POINTER_SIZE + 1 * WORD_SIZE;
 162 cananian 1.8              CLAZ_GCENTRY_OFF = 3 * POINTER_SIZE + 2 * WORD_SIZE;
 163 cananian 1.8              CLAZ_EXTRAINFO_OFF=4 * POINTER_SIZE + 2 * WORD_SIZE; 
 164 cananian 1.8              CLAZ_DISPLAY_OFF = CLAZ_EXTRAINFO_OFF +
 165 cananian 1.3.2.4              runtime.getExtraClazInfo().fields_size();
 166 cananian 1.3.2.5      }
 167 cananian 1.3.2.5      // hook to let our subclasses use a different classfieldmap
 168 cananian 1.3.2.5      protected FieldMap initClassFieldMap() {
 169 cananian 1.3.2.5          return new harpoon.Backend.Analysis.PackedClassFieldMap() {
 170 cananian 1.3.2.5              public int fieldSize(HField hf) {
 171 cananian 1.3.2.5                  HClass type = hf.getType();
 172 cananian 1.3.2.5                  return (!type.isPrimitive()) ? POINTER_SIZE :
 173 cananian 1.3.2.5                      (type==HClass.Double||type==HClass.Long) ? LONG_WORD_SIZE :
 174 cananian 1.3.2.5                      (type==HClass.Int||type==HClass.Float) ? WORD_SIZE :
 175 cananian 1.3.2.5                      (type==HClass.Short||type==HClass.Char) ? 2 : 1;
 176 cananian 1.3.2.5              }
 177 cananian 1.3.2.5              // on some archs we only need to align to WORD_SIZE
 178 cananian 1.3.2.5              public int fieldAlignment(HField hf) {
 179 cananian 1.3.2.5                  int align = super.fieldAlignment(hf);
 180 cananian 1.3.2.5                  return singleWordAlign ? Math.min(WORD_SIZE, align) : align;
 181 cananian 1.3.2.5              }
 182 cananian 1.3.2.5         };
 183 cananian 1.1.2.48     }
 184 cananian 1.1.2.48     // this method must be called to complete initialization before
 185 cananian 1.1.2.48     // the tree builder is used.
 186 cananian 1.1.2.48     protected void setClassHierarchy(ClassHierarchy ch) {
 187 cananian 1.1.2.48         this.cdm = new harpoon.Backend.Maps.DefaultClassDepthMap(ch);
 188 cananian 1.1.2.48         this.imm = new harpoon.Backend.Analysis.InterfaceMethodMap(ch);
 189 cananian 1.1.2.10         CLAZ_METHODS_OFF = CLAZ_DISPLAY_OFF + (1+cdm.maxDepth())*POINTER_SIZE;
 190 cananian 1.1.2.3      }
 191 cananian 1.1.2.20     // type declaration helper methods
 192 bdemsky  1.1.2.30     protected static Exp DECLARE(DerivationGenerator dg, HClass hc, Exp exp) {
 193 cananian 1.1.2.20         if (dg!=null) dg.putType(exp, hc);
 194 cananian 1.1.2.20         return exp;
 195 cananian 1.1.2.20     }
 196 bdemsky  1.1.2.30     protected static Exp DECLARE(DerivationGenerator dg, HClass hc, Temp t,
 197 cananian 1.1.2.20                                Exp exp) {
 198 cananian 1.1.2.20         if (dg!=null) dg.putTypeAndTemp(exp, hc, t);
 199 cananian 1.1.2.20         return exp;
 200 cananian 1.1.2.20     }
 201 bdemsky  1.1.2.30     protected static Exp DECLARE(DerivationGenerator dg, Derivation.DList dl,
 202 cananian 1.1.2.20                                Exp exp) {
 203 cananian 1.1.2.20         if (dg!=null) dg.putDerivation(exp, dl);
 204 cananian 1.1.2.20         return exp;
 205 cananian 1.1.2.20     }
 206 cananian 1.1.2.20 
 207 cananian 1.1.2.42     // pointer masking.
 208 cananian 1.1.2.42     protected Exp PTRMASK(TreeFactory tf, HCodeElement source,
 209 cananian 1.1.2.42                           DerivationGenerator dg,
 210 cananian 1.1.2.42                           Exp e) {
 211 cananian 1.1.2.42         if (pointerAlignment<2) return e;
 212 cananian 1.1.2.42         // declare result as derived pointer.
 213 cananian 1.1.2.42         CONST c = (POINTER_SIZE>WORD_SIZE) ?
 214 cananian 1.1.2.42             new CONST(tf, source, ~((long)(pointerAlignment-1))) :
 215 cananian 1.1.2.42             new CONST(tf, source, ~((int)(pointerAlignment-1))) ;
 216 cananian 1.1.2.42         return new BINOP
 217 cananian 1.1.2.42             (tf, source, Type.POINTER, Bop.AND, e, c);
 218 cananian 1.1.2.42     }
 219 cananian 1.1.2.7      // use the field offset map to get the object size (not including header)
 220 cananian 1.1.2.32     public int objectSize(HClass hc) {
 221 cananian 1.1.2.3          List l = cfm.fieldList(hc);
 222 cananian 1.1.2.3          if (l.size()==0) return 0;
 223 cananian 1.1.2.3          HField lastfield = (HField) l.get(l.size()-1);
 224 cananian 1.1.2.3          return cfm.fieldOffset(lastfield) + cfm.fieldSize(lastfield);
 225 cananian 1.1.2.38     }
 226 cananian 1.1.2.38     public int headerSize(HClass hc) { // hc is ignored
 227 cananian 1.1.2.38         return OBJECT_HEADER_SIZE;
 228 cananian 1.1.2.3      }
 229 cananian 1.1.2.1  
 230 cananian 1.1.2.1      // allocate 'length' bytes plus object header; fill in object header.
 231 cananian 1.1.2.1      // shift return pointer appropriately for an object reference.
 232 cananian 1.1.2.1      public Exp objAlloc(TreeFactory tf, HCodeElement source,
 233 cananian 1.1.2.20                         DerivationGenerator dg,
 234 cananian 1.1.2.25                         AllocationProperties ap,
 235 cananian 1.1.2.1                          HClass objectType, Exp length) {
 236 cananian 1.1.2.3          Temp Tobj = new Temp(tf.tempFactory(), "rt");
 237 cananian 1.1.2.45         // masked version of object pointer.
 238 cananian 1.1.2.45         Temp Tmasked = new Temp(tf.tempFactory(), "rt");
 239 cananian 1.1.2.45         Derivation.DList maskedDL = new Derivation.DList(Tobj, true, null);
 240 cananian 1.1.2.3          return new ESEQ
 241 cananian 1.1.2.3              (tf, source,
 242 cananian 1.1.2.3               new SEQ
 243 cananian 1.1.2.3               (tf, source,
 244 cananian 1.1.2.3                new MOVE // allocate memory; put pointer in Tobj.
 245 cananian 1.1.2.3                (tf, source,
 246 cananian 1.1.2.36                DECLARE(dg, objectType/*not an obj yet*/, Tobj,
 247 cananian 1.1.2.20                new TEMP(tf, source, Type.POINTER, Tobj)),
 248 cananian 1.1.2.12                as.memAlloc
 249 cananian 1.1.2.25                (tf, source, dg, ap,
 250 cananian 1.1.2.12                 new BINOP
 251 cananian 1.1.2.27                 (tf, source, Type.INT, Bop.ADD,
 252 cananian 1.1.2.12                  length,
 253 cananian 1.1.2.12                  new CONST(tf, source, OBJECT_HEADER_SIZE)))),
 254 cananian 1.1.2.3                new SEQ
 255 cananian 1.1.2.3                (tf, source,
 256 cananian 1.1.2.45                new MOVE // save a masked version of the pointer.
 257 cananian 1.1.2.45                (tf, source,
 258 cananian 1.1.2.45                 DECLARE(dg, maskedDL,
 259 cananian 1.1.2.45                 new TEMP(tf, source, Type.POINTER, Tmasked)),
 260 cananian 1.1.2.45                 PTRMASK(tf, source, dg,
 261 cananian 1.1.2.45                 DECLARE(dg, objectType/*not an obj yet*/, Tobj,
 262 cananian 1.1.2.45                 new TEMP(tf, source, Type.POINTER, Tobj)))),
 263 cananian 1.1.2.45               new SEQ
 264 cananian 1.1.2.45               (tf, source,
 265 cananian 1.1.2.3                 new MOVE // assign the new object a hashcode.
 266 cananian 1.1.2.3                 (tf, source,
 267 cananian 1.1.2.24                 DECLARE(dg, HClass.Void/*hashcode, not an object*/,
 268 cananian 1.1.2.3                  new MEM
 269 cananian 1.1.2.24                 (tf, source, Type.POINTER, /* hashcode is pointer size */
 270 cananian 1.1.2.3                   new BINOP
 271 cananian 1.1.2.3                   (tf, source, Type.POINTER, Bop.ADD,
 272 cananian 1.1.2.45                   DECLARE(dg, maskedDL,
 273 cananian 1.1.2.45                   new TEMP(tf, source, Type.POINTER, Tmasked)),
 274 cananian 1.1.2.24                   new CONST(tf, source, OBJ_HASH_OFF)))),
 275 cananian 1.1.2.23                 new BINOP // set the low bit to indicate an uninflated object.
 276 cananian 1.1.2.24                 (tf, source, Type.POINTER, Bop.ADD,
 277 cananian 1.1.2.45                  DECLARE(dg, maskedDL,
 278 cananian 1.1.2.45                  new TEMP(tf, source, Type.POINTER, Tmasked)),
 279 kkz      1.5                       new CONST(tf, source, (ap.setDynamicWBFlag()?3:1)))),
 280 cananian 1.1.2.3                 new MOVE // assign the new object a class pointer.
 281 cananian 1.1.2.3                 (tf, source,
 282 cananian 1.1.2.20                 DECLARE
 283 cananian 1.1.2.20                 (dg, HClass.Void/*claz pointer*/,
 284 cananian 1.1.2.20                  new MEM
 285 cananian 1.1.2.20                  (tf, source, Type.POINTER,
 286 cananian 1.1.2.20                   new BINOP
 287 cananian 1.1.2.20                   (tf, source, Type.POINTER, Bop.ADD,
 288 cananian 1.1.2.45                    DECLARE(dg, maskedDL,
 289 cananian 1.1.2.45                            new TEMP(tf, source, Type.POINTER, Tmasked)),
 290 cananian 1.1.2.20                    new CONST(tf, source, OBJ_CLAZ_OFF)))),
 291 cananian 1.1.2.48                 new NAME(tf, source, runtime.getNameMap().label(objectType)))))),
 292 cananian 1.1.2.3               // result of ESEQ is new object pointer
 293 cananian 1.1.2.20              DECLARE(dg, objectType/*finally an obj*/, Tobj,
 294 cananian 1.1.2.20              new TEMP(tf, source, Type.POINTER, Tobj)));
 295 kkz      1.6          }
 296 kkz      1.6      
 297 kkz      1.6          public Stm clearHashBit(TreeFactory tf, HCodeElement source,
 298 kkz      1.6                                  DerivationGenerator dg, Exp objExp) {
 299 kkz      1.6              // masked version of object pointer
 300 kkz      1.6              //Derivation.DList objectDL = dg.derivation(objExp);
 301 kkz      1.6              //assert objectDL != null : "huh?" + objExp;
 302 kkz      1.6              Temp Thash = new Temp(tf.tempFactory(), "cb");
 303 kkz      1.6              return new SEQ
 304 kkz      1.6                  (tf, source,
 305 kkz      1.6                   new MOVE // save a pointer to the hashcode field
 306 kkz      1.6                   (tf, source,
 307 kkz      1.6                    DECLARE(dg, HClass.Void/* pointer to hashcode */,
 308 kkz      1.6                    new TEMP(tf, source, Type.POINTER, Thash)),
 309 kkz      1.6                    new BINOP
 310 kkz      1.6                    (tf, source, Type.POINTER, Bop.ADD,
 311 kkz      1.6                     // DECLARE(dg, objectDL,
 312 kkz      1.6                             PTRMASK(tf, source, dg, objExp)/*)*/,
 313 kkz      1.6                     new CONST(tf, source, OBJ_HASH_OFF))),
 314 kkz      1.6                   new MOVE // clear next-to-low bit of hashcode
 315 kkz      1.6                   (tf, source,
 316 kkz      1.6                    DECLARE(dg, HClass.Void/*hashcode, not an object*/,
 317 kkz      1.6                    new MEM
 318 kkz      1.6                    (tf, source, Type.POINTER, /* hashcode is pointer size */
 319 kkz      1.6                     DECLARE(dg, HClass.Void,
 320 kkz      1.6                     new TEMP(tf, source, Type.POINTER, Thash)))),
 321 kkz      1.6                    new BINOP // mask out next-to-low bit of hashcode
 322 kkz      1.6                    (tf, source, Type.POINTER, Bop.AND,
 323 kkz      1.6                     DECLARE(dg, HClass.Void,
 324 kkz      1.6                     new MEM
 325 kkz      1.6                     (tf, source, Type.POINTER,
 326 kkz      1.6                      DECLARE(dg, HClass.Void,
 327 kkz      1.6                      new TEMP(tf, source, Type.POINTER, Thash)))),
 328 kkz      1.6                     new CONST
 329 kkz      1.6                     (tf, source, 
 330 kkz      1.6                      (POINTER_SIZE>WORD_SIZE) ? ~((long)2) : ~((int)2)))));
 331 cananian 1.1.2.1      }
 332 cananian 1.1.2.1  
 333 cananian 1.1.2.3      public Translation.Exp arrayLength(TreeFactory tf, HCodeElement source,
 334 cananian 1.1.2.20                                        DerivationGenerator dg,
 335 cananian 1.1.2.3                                         Translation.Exp arrayRef) {
 336 cananian 1.1.2.3          return new Translation.Ex
 337 cananian 1.1.2.3             (new MEM  
 338 cananian 1.1.2.1              (tf, source, Type.INT, // The "length" field is of type INT
 339 cananian 1.1.2.1               new BINOP
 340 cananian 1.1.2.1               (tf, source, Type.POINTER, Bop.ADD,
 341 cananian 1.1.2.45               fieldBase(tf, source, dg, arrayRef).unEx(tf),
 342 cananian 1.1.2.1                new CONST
 343 cananian 1.1.2.45               // offset from array base ptr.
 344 cananian 1.1.2.45               (tf, source, OBJ_ALENGTH_OFF-OBJ_FZERO_OFF))));
 345 cananian 1.1.2.1      }
 346 cananian 1.1.2.3      public Translation.Exp arrayNew(TreeFactory tf, HCodeElement source,
 347 cananian 1.1.2.20                                     DerivationGenerator dg,
 348 cananian 1.1.2.25                                     AllocationProperties ap,
 349 cananian 1.1.2.49                                     HClass arrayType, Translation.Exp length,
 350 cananian 1.1.2.49                                     boolean initialize) {
 351 cananian 1.3.2.1          assert arrayType.isArray();
 352 cananian 1.1.2.1          // temporary storage for created array.
 353 cananian 1.1.2.1          Temp Tarr = new Temp(tf.tempFactory(), "rt");
 354 cananian 1.1.2.1          // temporary storage for supplied length
 355 cananian 1.1.2.1          Temp Tlen = new Temp(tf.tempFactory(), "rt");
 356 cananian 1.1.2.49         // temporary storage for length to be initialized.
 357 cananian 1.1.2.49         Temp Tini = new Temp(tf.tempFactory(), "rt");
 358 cananian 1.1.2.1          // type of array components
 359 cananian 1.1.2.1          HClass comType = arrayType.getComponentType();
 360 cananian 1.1.2.1          // size of elements in array
 361 cananian 1.1.2.11         int elementSize = !comType.isPrimitive() ? POINTER_SIZE :
 362 cananian 1.1.2.11             (comType==HClass.Double || comType==HClass.Long) ? (WORD_SIZE*2) :
 363 cananian 1.1.2.11             (comType==HClass.Byte || comType==HClass.Boolean) ? 1 :
 364 cananian 1.1.2.11             (comType==HClass.Char || comType==HClass.Short) ? 2 :
 365 cananian 1.1.2.11             WORD_SIZE;
 366 cananian 1.1.2.49         Exp size =
 367 cananian 1.1.2.49             new BINOP // compute array data size:
 368 cananian 1.1.2.49             (tf, source, Type.INT, Bop.ADD,
 369 cananian 1.1.2.49              new BINOP // multiply...
 370 cananian 1.1.2.49              (tf, source, Type.INT, Bop.MUL,
 371 cananian 1.1.2.49               // ...array length by ...
 372 cananian 1.1.2.49               new TEMP(tf, source, Type.INT, Tlen),
 373 cananian 1.1.2.49               // ...element size...
 374 cananian 1.1.2.49               new CONST(tf, source, elementSize)),
 375 cananian 1.1.2.49              // and add WORD_SIZE (and more) for length field (and others)
 376 cananian 1.1.2.49              new CONST(tf, source, OBJ_AZERO_OFF - OBJ_FZERO_OFF));
 377 cananian 1.1.2.49         if (initialize) // save the 'size' value for re-use (if needed)
 378 cananian 1.1.2.49             size =
 379 cananian 1.1.2.49                 new ESEQ
 380 cananian 1.1.2.49                 (tf, source,
 381 cananian 1.1.2.49                  new MOVE // save 'size' in Tini
 382 cananian 1.1.2.49                  (tf, source,
 383 cananian 1.1.2.49                   new TEMP(tf, source, Type.INT, Tini),
 384 cananian 1.1.2.49                   size),
 385 cananian 1.1.2.49                  new TEMP(tf, source, Type.INT, Tini));
 386 cananian 1.1.2.37         Stm stm =
 387 cananian 1.1.2.16               new SEQ
 388 cananian 1.1.2.16               (tf, source,
 389 cananian 1.1.2.16                new MOVE // save 'length' in Tlen.
 390 cananian 1.1.2.16                (tf, source,
 391 cananian 1.1.2.16                 new TEMP(tf, source, Type.INT, Tlen),
 392 cananian 1.1.2.16                 length.unEx(tf)),
 393 cananian 1.1.2.16                new MOVE // save result in Tarr
 394 cananian 1.1.2.1                 (tf, source,
 395 cananian 1.1.2.36                 DECLARE(dg, arrayType/* not an obj yet*/, Tarr,
 396 cananian 1.1.2.20                         new TEMP(tf, source, Type.POINTER, Tarr)),
 397 cananian 1.1.2.1                  objAlloc // allocate array data
 398 cananian 1.1.2.25                 (tf, source, dg, ap, arrayType,
 399 cananian 1.1.2.49                  size)));
 400 cananian 1.1.2.49         // now initialize either just the object fields or the whole
 401 cananian 1.1.2.49         // array, depending on the value of the 'initialize' boolean.
 402 cananian 1.1.2.49         // (note this must happen before we set the length field, as
 403 cananian 1.1.2.49         //  the length falls between the object fields and the rest of
 404 cananian 1.1.2.49         //  the array)
 405 cananian 1.1.2.49         if (initialize || OBJ_ALENGTH_OFF != OBJ_FZERO_OFF) {
 406 cananian 1.1.2.49             Exp initlen = initialize ?
 407 cananian 1.1.2.49                 (Exp) new TEMP(tf, source, Type.INT, Tini) :
 408 cananian 1.1.2.49                 (Exp) new CONST(tf, source, OBJ_ALENGTH_OFF-OBJ_FZERO_OFF);
 409 cananian 1.1.2.37             stm = new SEQ
 410 cananian 1.1.2.37                 (tf, source, stm,
 411 cananian 1.1.2.37                  new NATIVECALL
 412 cananian 1.1.2.37                  (tf, source, null,
 413 cananian 1.1.2.37                   DECLARE(dg, HClass.Void/*c library function*/,
 414 cananian 1.1.2.37                   new NAME(tf, source, new Label
 415 cananian 1.1.2.48                            (runtime.getNameMap().c_function_name("memset")))),
 416 cananian 1.1.2.37                   new ExpList
 417 cananian 1.1.2.45                   (fieldBase(tf, source, dg, new Translation.Ex
 418 cananian 1.1.2.45                              (DECLARE(dg, arrayType/*not an obj yet*/, Tarr,
 419 cananian 1.1.2.45                               new TEMP(tf, source, Type.POINTER, Tarr))))
 420 cananian 1.1.2.45                    .unEx(tf),
 421 cananian 1.1.2.37                    new ExpList
 422 cananian 1.1.2.37                    (new CONST(tf, source, 0),
 423 cananian 1.1.2.37                     new ExpList
 424 cananian 1.1.2.49                     (initlen,
 425 cananian 1.1.2.37                      null)))));
 426 cananian 1.1.2.49         }
 427 cananian 1.1.2.49         // set length field of newly-created array.
 428 cananian 1.1.2.49         stm = new SEQ
 429 cananian 1.1.2.49             (tf, source, stm,
 430 cananian 1.1.2.49               new MOVE
 431 cananian 1.1.2.49               (tf, source,
 432 cananian 1.1.2.49                new MEM
 433 cananian 1.1.2.49                (tf, source, Type.INT, // length field is of type INT.
 434 cananian 1.1.2.49                 new BINOP // offset array base to get location of length field
 435 cananian 1.1.2.49                 (tf, source, Type.POINTER, Bop.ADD,
 436 cananian 1.1.2.49                 fieldBase(tf, source, dg, new Translation.Ex
 437 cananian 1.1.2.49                           (DECLARE(dg, arrayType/*not an obj yet*/, Tarr,
 438 cananian 1.1.2.49                            new TEMP(tf, source, Type.POINTER, Tarr))))
 439 cananian 1.1.2.49                 .unEx(tf),
 440 cananian 1.1.2.49                  new CONST(tf, source, OBJ_ALENGTH_OFF-OBJ_FZERO_OFF))),
 441 cananian 1.1.2.49                new TEMP(tf, source, Type.INT, Tlen))); // length from Tlen
 442 cananian 1.1.2.49         // and make an expression with the value of the array pointer.
 443 cananian 1.1.2.37         return new Translation.Ex
 444 cananian 1.1.2.37             (new ESEQ
 445 cananian 1.1.2.37              (tf, source, stm,
 446 cananian 1.1.2.1               // result of whole expression is the array pointer, in Tarr
 447 cananian 1.1.2.20              DECLARE(dg, arrayType/*finally an obj*/, Tarr,
 448 cananian 1.1.2.20                      new TEMP(tf, source, Type.POINTER, Tarr))));
 449 cananian 1.1.2.1      }
 450 cananian 1.1.2.1  
 451 cananian 1.1.2.52     public Translation.Exp componentOf(final TreeFactory tf,
 452 cananian 1.1.2.52                                        final HCodeElement source,
 453 cananian 1.1.2.52                                        final DerivationGenerator dg,
 454 cananian 1.1.2.52                                        final Translation.Exp arrayref,
 455 cananian 1.1.2.52                                        final Translation.Exp componentref) {
 456 cananian 1.1.2.52         List stmlist = new ArrayList(5);
 457 cananian 1.1.2.1          // component clazz pointer of arrayref
 458 cananian 1.1.2.20         Exp e0 = DECLARE(dg, HClass.Void/*component claz ptr*/,
 459 cananian 1.1.2.20                  new MEM(tf, source, Type.POINTER,
 460 cananian 1.1.2.1                           new BINOP // offset to get component type pointer
 461 cananian 1.1.2.1                           (tf, source, Type.POINTER, Bop.ADD,
 462 cananian 1.1.2.1                            new CONST(tf, source, CLAZ_COMPONENT_OFF),
 463 cananian 1.1.2.1                            // dereference object to claz structure.
 464 cananian 1.1.2.45                           _claz_(tf, source, dg, arrayref))));
 465 cananian 1.1.2.1          // move claz pointer of arrayref component to a temporary variable.
 466 cananian 1.1.2.52         final Temp Tac = new Temp(tf.tempFactory(), "rt");
 467 cananian 1.1.2.1          Stm s0 = new MOVE(tf, source,
 468 cananian 1.1.2.20                           DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,
 469 cananian 1.1.2.20                                   new TEMP(tf, source, Type.POINTER, Tac)),
 470 cananian 1.1.2.1                            e0); // now use Tac instead of e0.
 471 cananian 1.1.2.52         stmlist.add(s0);
 472 cananian 1.1.2.52         // class pointer of componentref
 473 cananian 1.1.2.52         Exp e1 = _claz_(tf, source, dg, componentref);
 474 cananian 1.1.2.52         // move claz pointer of componentref to a temporary variable.
 475 cananian 1.1.2.52         final Temp Tcc = new Temp(tf.tempFactory(), "rt");
 476 cananian 1.1.2.52         Stm s1 = new MOVE(tf, source,
 477 cananian 1.1.2.52                           DECLARE(dg, HClass.Void/*component claz ptr*/, Tcc,
 478 cananian 1.1.2.52                                   new TEMP(tf, source, Type.POINTER, Tcc)),
 479 cananian 1.1.2.52                           e1); // now use Tcc instead of e1.
 480 cananian 1.1.2.52         stmlist.add(s1);
 481 cananian 1.1.2.1          // class depth of arrayref component type.
 482 cananian 1.1.2.1          Exp e2 = new MEM(tf, source, Type.INT,
 483 cananian 1.1.2.1                           new BINOP // offset to class depth.
 484 cananian 1.1.2.1                           (tf, source, Type.POINTER, Bop.ADD,
 485 cananian 1.1.2.1                            new CONST(tf, source, CLAZ_DEPTH_OFF),
 486 cananian 1.1.2.20                           DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,
 487 cananian 1.1.2.20                                   new TEMP(tf, source, Type.POINTER, Tac))));
 488 cananian 1.1.2.52         // if arrayref is an array with an ultimately interface base type
 489 cananian 1.1.2.52         // (after all the dims have been stripped away), we need to look
 490 cananian 1.1.2.52         // through the interfacelist to implement instanceof, instead of
 491 cananian 1.1.2.52         // relying on the class display table.  So we need to identify these
 492 cananian 1.1.2.52         // cases. [we actually look at the component type of the arrayref]
 493 cananian 1.1.2.52         // For arrays of interfaces and interfaces, e2==0 and MEM(e0+e2)!=e0
 494 cananian 1.1.2.52         // MEM(e0+e2)==e0 for all others.  check e2==0 first to avoid an
 495 cananian 1.1.2.52         // unnecessary memory reference (for everything except Object[]
 496 cananian 1.1.2.52         // arrays).
 497 cananian 1.1.2.52         final Temp Tcd = new Temp(tf.tempFactory(), "rt"); // class depth
 498 cananian 1.1.2.52         Stm s2 = new MOVE(tf, source,
 499 cananian 1.1.2.52                           new TEMP(tf, source, Type.INT, Tcd),
 500 cananian 1.1.2.52                           e2); // now use Tcd instead of e2.
 501 cananian 1.1.2.52         stmlist.add(s2);
 502 cananian 1.1.2.52         final Label Lisinterface = new Label();
 503 cananian 1.1.2.52         final Label Lmaybeinterface = new Label();
 504 cananian 1.1.2.52         final Label Lnotinterface = new Label();
 505 cananian 1.1.2.52         stmlist.add
 506 cananian 1.1.2.52             (new CJUMP(tf, source,
 507 cananian 1.1.2.52                        new BINOP(tf, source, Type.INT, Bop.CMPEQ,
 508 cananian 1.1.2.52                                  new TEMP(tf, source, Type.INT, Tcd),
 509 cananian 1.1.2.52                                  new CONST(tf, source, 0)),
 510 cananian 1.1.2.52                        Lmaybeinterface, Lnotinterface));
 511 cananian 1.1.2.52         stmlist.add
 512 cananian 1.1.2.52             (new LABEL(tf, source, Lmaybeinterface, false));
 513 cananian 1.1.2.52         // now check whether MEM(e0+e2)==NULL (then this is interface type!)
 514 cananian 1.1.2.52         stmlist.add
 515 cananian 1.1.2.52             (new CJUMP(tf, source,
 516 cananian 1.1.2.52                        new BINOP
 517 cananian 1.1.2.52                        (tf, source, Type.POINTER, Bop.CMPEQ,
 518 cananian 1.1.2.52                         DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,
 519 cananian 1.1.2.52                         new TEMP(tf, source, Type.POINTER, Tac)),
 520 cananian 1.1.2.52                         DECLARE(dg, HClass.Void/*claz ptr in display*/,
 521 cananian 1.1.2.52                         new MEM
 522 cananian 1.1.2.52                         (tf, source, Type.POINTER,
 523 cananian 1.1.2.52                          new BINOP
 524 cananian 1.1.2.52                          (tf, source, Type.POINTER, Bop.ADD,
 525 cananian 1.1.2.52                           new BINOP
 526 cananian 1.1.2.52                           (tf, source, Type.INT, Bop.ADD,
 527 cananian 1.1.2.52                            new CONST(tf, source, CLAZ_DISPLAY_OFF),
 528 cananian 1.1.2.52                            new TEMP(tf, source, Type.INT, Tcd)),
 529 cananian 1.1.2.52                           DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,
 530 cananian 1.1.2.52                           new TEMP(tf, source, Type.POINTER, Tac)))))),
 531 cananian 1.1.2.52                        Lnotinterface, Lisinterface));
 532 cananian 1.1.2.52 
 533 cananian 1.1.2.52         /* common initialization code (selects interface/non-interface case) */
 534 cananian 1.1.2.52         final Stm initstm = Stm.toStm(stmlist);
 535 cananian 1.1.2.52 
 536 cananian 1.1.2.52         // NON-INTERFACE CASE: ---------------------------
 537 cananian 1.1.2.1          // we assert that MEM(e0+e2)==e0 by definition
 538 cananian 1.1.2.1          // that is, element of class display at class_depth is the class itself
 539 cananian 1.1.2.1          // so, the component-of check is just whether MEM(e1+e2)==e0
 540 cananian 1.1.2.54         final Translation.Exp case1exp = _instanceOf_class
 541 cananian 1.1.2.54             (tf, source, dg,
 542 cananian 1.1.2.54              // reference the claz structure of the component object
 543 cananian 1.1.2.54              DECLARE(dg, HClass.Void/*componentref claz ptr*/, Tcc,//e1
 544 cananian 1.1.2.54                      new TEMP(tf, source, Type.POINTER, Tcc)),
 545 cananian 1.1.2.54              // reference the component claz of the array claz
 546 cananian 1.1.2.54              DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,//e0
 547 cananian 1.1.2.54                      new TEMP(tf, source, Type.POINTER, Tac)),
 548 cananian 1.1.2.54              // offset of the component claz in the display
 549 cananian 1.1.2.54              new TEMP(tf, source, Type.INT, Tcd));
 550 cananian 1.1.2.54 
 551 cananian 1.1.2.54         // INTERFACE CASE: ------------------------------
 552 cananian 1.1.2.54         // interface type: linear search through interface list.
 553 cananian 1.1.2.54         // compile as:
 554 cananian 1.1.2.54         //    for (il=obj->claz->interfz; *il!=null; il++)
 555 cananian 1.1.2.54         //       if (*il==classTypeLabel) return true;
 556 cananian 1.1.2.54         //    return false;
 557 cananian 1.1.2.54         // [classTypeLabel=e0 ; obj->claz = e1]
 558 cananian 1.1.2.54         final Translation.Exp case2exp = _instanceOf_interface
 559 cananian 1.1.2.54             (tf, source, dg,
 560 cananian 1.1.2.54              // reference the claz structure of the component object
 561 cananian 1.1.2.54              DECLARE(dg, HClass.Void/*cmpntref claz ptr*/, Tcc,
 562 cananian 1.1.2.54                      new TEMP(tf, source, Type.POINTER, Tcc)),//e1
 563 cananian 1.1.2.54              // reference the component claz of the array claz
 564 cananian 1.1.2.54              DECLARE(dg, HClass.Void/*component claz ptr*/, Tac,
 565 cananian 1.1.2.54                      new TEMP(tf, source, Type.POINTER, Tac)));
 566 cananian 1.1.2.54         
 567 cananian 1.1.2.54         // okay, put pieces together.
 568 cananian 1.1.2.54 
 569 cananian 1.1.2.54         return new Translation.Cx() {
 570 cananian 1.1.2.54             public Stm unCxImpl(TreeFactory xxx, Label iftrue, Label iffalse) {
 571 cananian 1.1.2.54                 List _stmlist_ = new ArrayList(5);
 572 cananian 1.1.2.54                 // first comes init code
 573 cananian 1.1.2.54                 _stmlist_.add(initstm);
 574 cananian 1.1.2.54                 // then comes non-interface array case.
 575 cananian 1.1.2.54                 _stmlist_.add(new LABEL(tf, source, Lnotinterface, false));
 576 cananian 1.1.2.54                 _stmlist_.add(case1exp.unCx(tf, iftrue, iffalse));
 577 cananian 1.1.2.54                 // finally comes interface array case:
 578 cananian 1.1.2.54                 _stmlist_.add(new LABEL(tf, source, Lisinterface, false));
 579 cananian 1.1.2.54                 _stmlist_.add(case2exp.unCx(tf, iftrue, iffalse));
 580 cananian 1.1.2.54                 // done!
 581 cananian 1.1.2.54                 return Stm.toStm(_stmlist_);
 582 cananian 1.1.2.54             }
 583 cananian 1.1.2.54         };
 584 cananian 1.1.2.54     }
 585 cananian 1.1.2.54 
 586 cananian 1.1.2.54     private Translation.Exp _instanceOf_class(final TreeFactory tf,
 587 cananian 1.1.2.54                                               final HCodeElement source,
 588 cananian 1.1.2.54                                               final DerivationGenerator dg,
 589 cananian 1.1.2.54                                               Exp this_claz_exp,
 590 cananian 1.1.2.54                                               Exp checked_claz_exp,
 591 cananian 1.1.2.54                                               Exp class_offset_exp) {
 592 cananian 1.1.2.54         // class type: single lookup and comparison.
 593 cananian 1.1.2.54         // compile as:
 594 cananian 1.1.2.54         //    return obj->claz->display[CONST_OFF(classType)]==classType;
 595 cananian 1.1.2.54         // let e0 = checked_claz_exp (claz ptr corresponding to classType)
 596 cananian 1.1.2.54         //     e1 = this_claz_exp    (obj->claz)
 597 cananian 1.1.2.54         //     e2 = class_offset_exp (CONST_OFF(classType))
 598 cananian 1.1.2.54         // we assert that MEM(e0+e2+k)==e0 by definition
 599 cananian 1.1.2.54         // that is, element of class display at class_depth is the class itself
 600 cananian 1.1.2.54         //         claz->display[CONST_OFF(claz)]==claz
 601 cananian 1.1.2.54         // so, the component-of check is just whether MEM(e1+e2+k)==e0
 602 cananian 1.1.2.54         return new Translation.Ex
 603 cananian 1.1.2.52            (new BINOP
 604 cananian 1.1.2.1              (tf, source, Type.POINTER, Bop.CMPEQ,
 605 cananian 1.1.2.20              DECLARE(dg, HClass.Void/*claz ptr in display*/,
 606 cananian 1.1.2.1               new MEM
 607 cananian 1.1.2.1               (tf, source, Type.POINTER,
 608 cananian 1.1.2.1                new BINOP
 609 cananian 1.1.2.1                (tf, source, Type.POINTER, Bop.ADD,
 610 cananian 1.1.2.1                 new BINOP
 611 wbeebee  1.1.2.39                (tf, source, Type.INT, Bop.ADD,
 612 cananian 1.1.2.1                  new CONST(tf, source, CLAZ_DISPLAY_OFF),
 613 cananian 1.1.2.54                 class_offset_exp),//e2
 614 cananian 1.1.2.54                this_claz_exp))),//e1
 615 cananian 1.1.2.54              checked_claz_exp));//e0
 616 cananian 1.1.2.54     }
 617 cananian 1.1.2.54     private Translation.Exp _instanceOf_interface(final TreeFactory tf,
 618 cananian 1.1.2.54                                                   final HCodeElement source,
 619 cananian 1.1.2.54                                                   final DerivationGenerator dg,
 620 cananian 1.1.2.54                                                   final Exp this_claz_exp,
 621 cananian 1.1.2.54                                                   final Exp checked_claz_exp) {
 622 cananian 1.1.2.52         // interface type: linear search through interface list.
 623 cananian 1.1.2.52         // compile as:
 624 cananian 1.1.2.52         //    for (il=obj->claz->interfz; *il!=null; il++)
 625 cananian 1.1.2.52         //       if (*il==classTypeLabel) return true;
 626 cananian 1.1.2.52         //    return false;
 627 cananian 1.1.2.54         
 628 cananian 1.1.2.52         // make our iteration variable.
 629 cananian 1.1.2.52         final Temp Til = new Temp(tf.tempFactory(), "rt"); // il
 630 cananian 1.1.2.52         // three labels
 631 cananian 1.1.2.52         final Label Ladv = new Label();
 632 cananian 1.1.2.52         final Label Ltop = new Label();
 633 cananian 1.1.2.52         final Label Ltst = new Label();
 634 cananian 1.1.2.54 
 635 cananian 1.1.2.54         return new Translation.Cx() {
 636 cananian 1.1.2.52             public Stm unCxImpl(TreeFactory xxx, Label iftrue, Label iffalse) {
 637 cananian 1.1.2.52                 List _stmlist_ = new ArrayList(8);
 638 cananian 1.1.2.52                 // initialize Til.
 639 cananian 1.1.2.52                 _stmlist_.add
 640 cananian 1.1.2.52                 (new MOVE
 641 cananian 1.1.2.52                  (tf, source,
 642 cananian 1.1.2.52                   DECLARE(dg, HClass.Void/*interface list ptr*/,
 643 cananian 1.1.2.52                   new TEMP(tf, source, Type.POINTER, Til)),
 644 cananian 1.1.2.52                   // dereference claz structure for interface list ptr
 645 cananian 1.1.2.52                   DECLARE(dg, HClass.Void/*interface list ptr*/,
 646 cananian 1.1.2.52                   new MEM(tf, source, Type.POINTER,
 647 cananian 1.1.2.52                           new BINOP // offset to get interface pointer
 648 cananian 1.1.2.52                           (tf, source, Type.POINTER, Bop.ADD,
 649 cananian 1.1.2.54                            this_claz_exp,
 650 cananian 1.1.2.52                            new CONST(tf, source, CLAZ_INTERFZ_OFF))))));
 651 cananian 1.1.2.52                 // jmp Ltst
 652 cananian 1.1.2.52                 _stmlist_.add(new JUMP(tf, source, Ltst));
 653 cananian 1.1.2.52                 // loop body: test *il against Lclaz.
 654 cananian 1.1.2.52                 _stmlist_.add(new LABEL(tf, source, Ltop, false));
 655 cananian 1.1.2.52                 _stmlist_.add
 656 cananian 1.1.2.52                 (new CJUMP
 657 cananian 1.1.2.52                  (tf, source,
 658 cananian 1.1.2.52                   new BINOP
 659 cananian 1.1.2.52                   (tf, source, Type.POINTER, Bop.CMPEQ,
 660 cananian 1.1.2.52                    DECLARE(dg, HClass.Void/*claz ptr for interface*/,
 661 cananian 1.1.2.52                    new MEM(tf, source, Type.POINTER,
 662 cananian 1.1.2.52                            DECLARE(dg, HClass.Void/*intrfce lst ptr*/,
 663 cananian 1.1.2.52                            new TEMP(tf, source, Type.POINTER, Til)))),
 664 cananian 1.1.2.54                    checked_claz_exp),
 665 cananian 1.1.2.52                   iftrue, Ladv));
 666 cananian 1.1.2.52                 // advance il
 667 cananian 1.1.2.52                 _stmlist_.add(new LABEL(tf, source, Ladv, false));
 668 cananian 1.1.2.52                 _stmlist_.add
 669 cananian 1.1.2.52                 (new MOVE
 670 cananian 1.1.2.52                  (tf, source,
 671 cananian 1.1.2.52                   DECLARE(dg, HClass.Void/*intrfce lst ptr*/, Til,
 672 cananian 1.1.2.52                   new TEMP(tf, source, Type.POINTER, Til)),
 673 cananian 1.1.2.52                   new BINOP
 674 cananian 1.1.2.52                   (tf, source, Type.POINTER, Bop.ADD,
 675 cananian 1.1.2.52                    DECLARE(dg, HClass.Void/*intrfce lst ptr*/, Til,
 676 cananian 1.1.2.52                    new TEMP(tf, source, Type.POINTER, Til)),
 677 cananian 1.1.2.52                    new CONST(tf, source, POINTER_SIZE))));
 678 cananian 1.1.2.52                 // loop guard: test *il against null.
 679 cananian 1.1.2.52                 _stmlist_.add(new LABEL(tf, source, Ltst, false));
 680 cananian 1.1.2.52                 _stmlist_.add
 681 cananian 1.1.2.52                 (new CJUMP
 682 cananian 1.1.2.52                  (tf, source,
 683 cananian 1.1.2.52                   new BINOP
 684 cananian 1.1.2.52                   (tf, source, Type.POINTER, Bop.CMPEQ,
 685 cananian 1.1.2.52                    DECLARE(dg, HClass.Void/*claz ptr, maybe null*/,
 686 cananian 1.1.2.52                    new MEM(tf, source, Type.POINTER,
 687 cananian 1.1.2.52                            DECLARE(dg, HClass.Void/*in lst ptr*/, Til,
 688 cananian 1.1.2.52                            new TEMP(tf, source, Type.POINTER, Til)))),
 689 cananian 1.1.2.52                    new CONST(tf, source) /*null constant*/),
 690 cananian 1.1.2.52                   iffalse, Ltop));
 691 cananian 1.1.2.1  
 692 cananian 1.1.2.52                 // okay, tie them together with SEQs.
 693 cananian 1.1.2.52                 return Stm.toStm(_stmlist_);
 694 cananian 1.1.2.52             }
 695 cananian 1.1.2.52         };
 696 cananian 1.1.2.1      }
 697 cananian 1.1.2.1  
 698 cananian 1.1.2.3      public Translation.Exp instanceOf(final TreeFactory tf,
 699 cananian 1.1.2.3                                        final HCodeElement source,
 700 cananian 1.1.2.20                                       final DerivationGenerator dg,
 701 cananian 1.1.2.3                                        final Translation.Exp objref,
 702 cananian 1.1.2.3                                        final HClass classType)
 703 cananian 1.1.2.3      {
 704 cananian 1.1.2.54         // the claz structure of objref
 705 cananian 1.1.2.54         Exp this_claz_exp = _claz_(tf, source, dg, objref);
 706 cananian 1.1.2.54         // the claz structure of classType
 707 cananian 1.1.2.54         Label Lclaz = runtime.getNameMap().label(classType);
 708 cananian 1.1.2.54         Exp checked_claz_exp = 
 709 cananian 1.1.2.54             DECLARE(dg, HClass.Void/*hardwired claz ptr*/,
 710 cananian 1.1.2.54                     new NAME(tf, source, Lclaz)); // claz pointer
 711 cananian 1.1.2.1          // two cases: class or interface type.
 712 cananian 1.1.2.29         if (HClassUtil.baseClass(classType).isInterface()) {
 713 cananian 1.1.2.1              // interface type: linear search through interface list.
 714 cananian 1.1.2.54             return _instanceOf_interface
 715 cananian 1.1.2.54                 (tf, source, dg, this_claz_exp, checked_claz_exp);
 716 cananian 1.1.2.1          } else {
 717 cananian 1.1.2.1              // class type: single lookup and comparison.
 718 cananian 1.1.2.1              // compile as:
 719 cananian 1.1.2.1              //    return obj->claz->display[CONST_OFF(classType)]==classType;
 720 cananian 1.1.2.54 
 721 cananian 1.1.2.54             // constant offset for classType in display:
 722 cananian 1.1.2.3              int class_offset = cdm.classDepth(classType) * POINTER_SIZE;
 723 cananian 1.1.2.54             Exp class_offset_exp = new CONST(tf, source, class_offset);
 724 cananian 1.1.2.1  
 725 cananian 1.1.2.54             return _instanceOf_class
 726 cananian 1.1.2.54                 (tf, source, dg,
 727 cananian 1.1.2.54                  this_claz_exp, checked_claz_exp, class_offset_exp);
 728 cananian 1.1.2.3          }
 729 cananian 1.1.2.3      }
 730 cananian 1.1.2.3  
 731 cananian 1.1.2.23     // XXX in single-threaded mode, this can be a NOP.
 732 cananian 1.1.2.3      public Translation.Exp monitorEnter(TreeFactory tf, HCodeElement source,
 733 cananian 1.1.2.20                                         DerivationGenerator dg,
 734 cananian 1.1.2.3                                          Translation.Exp objectref) {
 735 cananian 1.1.2.41         if (noSync) return objectref; // may have side-effects.
 736 cananian 1.1.2.23         // call FNI_MonitorEnter()
 737 cananian 1.1.2.23         return new Translation.Nx(_call_FNI_Monitor(tf, source, dg, objectref,
 738 cananian 1.1.2.23                                                     true));
 739 cananian 1.1.2.3      }
 740 cananian 1.1.2.23     // XXX in single-threaded mode, this can be a NOP.
 741 cananian 1.1.2.3      public Translation.Exp monitorExit(TreeFactory tf, HCodeElement source,
 742 cananian 1.1.2.20                                        DerivationGenerator dg,
 743 cananian 1.1.2.3                                         Translation.Exp objectref) {
 744 cananian 1.1.2.41         if (noSync) return objectref; // may have side-effects.
 745 cananian 1.1.2.23         // call FNI_MonitorExit()
 746 cananian 1.1.2.23         return new Translation.Nx(_call_FNI_Monitor(tf, source, dg, objectref,
 747 cananian 1.1.2.23                                                     false));
 748 cananian 1.1.2.23     }
 749 cananian 1.1.2.23     /** wrap objectref and then call FNI_Monitor{Enter|Exit}() */
 750 cananian 1.7          protected Stm _call_FNI_Monitor(TreeFactory tf, HCodeElement source,
 751 cananian 1.1.2.23                                   DerivationGenerator dg,
 752 cananian 1.1.2.23                                   Translation.Exp objectref,
 753 cananian 1.1.2.23                                   boolean isEnter/*else exit*/) {
 754 cananian 1.1.2.23         // keep this synchronized with StubCode.java
 755 cananian 1.1.2.23         // and Runtime/include/jni-private.h
 756 cananian 1.1.2.23         final int REF_OFFSET = 3 * POINTER_SIZE;
 757 cananian 1.1.2.23 
 758 cananian 1.1.2.23         // first get JNIEnv *
 759 cananian 1.1.2.23         Temp envT = new Temp(tf.tempFactory(), "env");
 760 cananian 1.1.2.23         Stm result0 = new NATIVECALL
 761 cananian 1.1.2.23             (tf, source, (TEMP)
 762 cananian 1.1.2.23              DECLARE(dg, HClass.Void/* JNIEnv * */, envT,
 763 cananian 1.1.2.23              new TEMP(tf, source, Type.POINTER, envT)) /*retval*/,
 764 cananian 1.1.2.23              DECLARE(dg, HClass.Void/* c function ptr */,
 765 cananian 1.1.2.23              new NAME(tf, source, new Label
 766 cananian 1.1.2.48                       (runtime.getNameMap().c_function_name("FNI_GetJNIEnv")))),
 767 cananian 1.1.2.23              null/* no args*/);
 768 cananian 1.1.2.23 
 769 cananian 1.1.2.23         // wrap objectref.
 770 cananian 1.1.2.23         Temp objT = new Temp(tf.tempFactory(), "obj");
 771 cananian 1.1.2.23         result0 = new SEQ
 772 cananian 1.1.2.23             (tf, source, result0,
 773 cananian 1.1.2.23              new NATIVECALL
 774 cananian 1.1.2.23              (tf, source, (TEMP)
 775 cananian 1.1.2.23               DECLARE(dg, HClass.Void/* jobject */, objT,
 776 cananian 1.1.2.23               new TEMP(tf, source, Type.POINTER, objT)) /*retval*/,
 777 cananian 1.1.2.23               DECLARE(dg, HClass.Void/* c function ptr */,
 778 cananian 1.1.2.23               new NAME(tf, source, new Label
 779 cananian 1.1.2.48                        (runtime.getNameMap().c_function_name("FNI_NewLocalRef")))),
 780 cananian 1.1.2.23               new ExpList
 781 cananian 1.1.2.23               (DECLARE(dg, HClass.Void/* JNIEnv * */, envT,
 782 cananian 1.1.2.23                new TEMP(tf, source, Type.POINTER, envT)),
 783 cananian 1.1.2.23                new ExpList
 784 cananian 1.1.2.23                (objectref.unEx(tf), null))));
 785 cananian 1.1.2.23 
 786 cananian 1.1.2.23         // call FNI_MonitorEnter or FNI_MonitorExit
 787 cananian 1.1.2.23         // proto is 'jint FNI_Monitor<foo>(JNIEnv *env, jobject obj);
 788 cananian 1.1.2.23         // i'm going to be anal and make a temp for the return value,
 789 cananian 1.1.2.23         // because some architectures might conceivably do weird things if
 790 cananian 1.1.2.23         // i just pretend the function is void.  but we don't need the retval.
 791 cananian 1.1.2.23         Temp disT = new Temp(tf.tempFactory(), "discard");
 792 cananian 1.1.2.23         Stm result1 = new NATIVECALL
 793 cananian 1.1.2.23             (tf, source,
 794 cananian 1.1.2.23              new TEMP(tf, source, Type.INT, disT) /*retval*/,
 795 cananian 1.1.2.23              DECLARE(dg, HClass.Void/* c function ptr */,
 796 cananian 1.1.2.23              new NAME(tf, source, new Label
 797 cananian 1.1.2.48                       (runtime.getNameMap().c_function_name
 798 cananian 1.1.2.23                        (isEnter?"FNI_MonitorEnter":"FNI_MonitorExit")))),
 799 cananian 1.1.2.23              new ExpList
 800 cananian 1.1.2.23              (DECLARE(dg, HClass.Void/* JNIEnv * */, envT,
 801 cananian 1.1.2.23               new TEMP(tf, source, Type.POINTER, envT)),
 802 cananian 1.1.2.23               new ExpList
 803 cananian 1.1.2.23               (DECLARE(dg, HClass.Void/* jobject */, objT,
 804 cananian 1.1.2.23                new TEMP(tf, source, Type.POINTER, objT)),
 805 cananian 1.1.2.23                null)));
 806 cananian 1.1.2.23 
 807 cananian 1.1.2.23         // okay, now free the localref and we're set.
 808 cananian 1.1.2.23         result1 = new SEQ
 809 cananian 1.1.2.23             (tf, source, result1,
 810 cananian 1.1.2.23              new NATIVECALL
 811 cananian 1.1.2.23              (tf, source, null/*void retval*/,
 812 cananian 1.1.2.23               DECLARE(dg, HClass.Void/* c function ptr */,
 813 cananian 1.1.2.48               new NAME(tf, source, new Label(runtime.getNameMap().c_function_name
 814 cananian 1.1.2.28                                              ("FNI_DeleteLocalRefsUpTo")))),
 815 cananian 1.1.2.23               new ExpList
 816 cananian 1.1.2.23               (DECLARE(dg, HClass.Void/* JNIEnv * */, envT,
 817 cananian 1.1.2.23                new TEMP(tf, source, Type.POINTER, envT)),
 818 cananian 1.1.2.23                new ExpList
 819 cananian 1.1.2.23                (DECLARE(dg, HClass.Void/* jobject */, objT,
 820 cananian 1.1.2.23                 new TEMP(tf, source, Type.POINTER, objT)),
 821 cananian 1.1.2.23                 null))));
 822 cananian 1.1.2.23         
 823 cananian 1.1.2.23         return new SEQ(tf, source, result0, result1);
 824 cananian 1.1.2.3      }
 825 cananian 1.1.2.3  
 826 cananian 1.1.2.3      public Translation.Exp objectNew(TreeFactory tf, HCodeElement source,
 827 cananian 1.1.2.20                                      DerivationGenerator dg,
 828 cananian 1.1.2.25                                      AllocationProperties ap,
 829 cananian 1.1.2.9                                       HClass classType, boolean initialize) {
 830 cananian 1.3.2.1          assert !classType.isArray();
 831 cananian 1.3.2.1          assert !classType.isPrimitive();
 832 cananian 1.1.2.9          int length = objectSize(classType);
 833 cananian 1.1.2.25         Exp object = objAlloc(tf, source, dg, ap, classType,
 834 cananian 1.1.2.9                                new CONST(tf, source, length));
 835 cananian 1.1.2.9          if (initialize) {
 836 cananian 1.1.2.9              // use memset to initialize all fields to 0.
 837 cananian 1.1.2.9              final Temp t = new Temp(tf.tempFactory());
 838 cananian 1.1.2.9              object = new ESEQ
 839 cananian 1.1.2.9                  (tf, source,
 840 cananian 1.1.2.9                   new SEQ
 841 cananian 1.1.2.9                   (tf, source,
 842 cananian 1.1.2.9                    new MOVE
 843 cananian 1.1.2.9                    (tf, source,
 844 cananian 1.1.2.20                    DECLARE(dg, classType, t,
 845 cananian 1.1.2.20                    new TEMP(tf, source, Type.POINTER, t)),
 846 cananian 1.1.2.9                     object),
 847 cananian 1.1.2.9                    new NATIVECALL
 848 cananian 1.1.2.9                    (tf, source, null,
 849 cananian 1.1.2.20                    DECLARE(dg, HClass.Void/*c library function*/,
 850 cananian 1.1.2.21                    new NAME(tf, source, new Label
 851 cananian 1.1.2.48                             (runtime.getNameMap().c_function_name("memset")))),
 852 cananian 1.1.2.9                     new ExpList
 853 cananian 1.1.2.9                     (new BINOP
 854 cananian 1.1.2.9                      (tf, source, Type.POINTER, Bop.ADD,
 855 cananian 1.1.2.20                      DECLARE(dg, classType, t,
 856 cananian 1.1.2.20                      new TEMP(tf, source, Type.POINTER, t)),
 857 cananian 1.1.2.9                       new CONST(tf, source, OBJ_FZERO_OFF)),
 858 cananian 1.1.2.9                      new ExpList
 859 cananian 1.1.2.9                      (new CONST(tf, source, 0),
 860 cananian 1.1.2.9                       new ExpList
 861 cananian 1.1.2.9                       (new CONST(tf, source, length),
 862 cananian 1.1.2.9                        null))))),
 863 cananian 1.1.2.20                  DECLARE(dg, classType, t,
 864 cananian 1.1.2.20                  new TEMP(tf, source, Type.POINTER, t)));
 865 cananian 1.1.2.9          }
 866 cananian 1.1.2.9          return new Translation.Ex(object);
 867 cananian 1.1.2.33     }
 868 cananian 1.1.2.33 
 869 cananian 1.1.2.33     public Translation.Exp classConst(TreeFactory tf, HCodeElement source,
 870 cananian 1.1.2.33                           DerivationGenerator dg, HClass classData) {
 871 cananian 1.1.2.33         Exp clsref = new NAME(tf, source,
 872 cananian 1.1.2.48                               runtime.getNameMap().label(classData, "classobj"));
 873 cananian 1.1.2.40         //let this NAME be HClass.Void, since it points at a static object
 874 cananian 1.1.2.40         //which the gc doesn't need to know about.  If we give it a type,
 875 cananian 1.1.2.40         //then the derivation generator will get confused by derived pointers
 876 cananian 1.1.2.40         //to it, since it doesn't live in a canonical temp.
 877 cananian 1.1.2.40         /*DECLARE(dg, linker.forName("java.lang.Class"), clsref);*/
 878 cananian 1.1.2.33         return new Translation.Ex(clsref);
 879 cananian 1.1.2.33     }
 880 cananian 1.1.2.33     public Translation.Exp fieldConst(TreeFactory tf, HCodeElement source,
 881 cananian 1.1.2.33                           DerivationGenerator dg, HField fieldData) {
 882 cananian 1.1.2.33         Exp fldref = new NAME(tf, source,
 883 cananian 1.1.2.48                               runtime.getNameMap().label(fieldData, "obj"));
 884 cananian 1.1.2.40         //let this NAME be HClass.Void, since it points at a static object
 885 cananian 1.1.2.40         //which the gc doesn't need to know about.  If we give it a type,
 886 cananian 1.1.2.40         //then the derivation generator will get confused by derived pointers
 887 cananian 1.1.2.40         //to it, since it doesn't live in a canonical temp.
 888 cananian 1.1.2.40         /*DECLARE(dg, linker.forName("java.lang.reflect.Field"), fldref);*/
 889 cananian 1.1.2.33         return new Translation.Ex(fldref);
 890 cananian 1.1.2.33     }
 891 cananian 1.1.2.33     public Translation.Exp methodConst(TreeFactory tf, HCodeElement source,
 892 cananian 1.1.2.33                            DerivationGenerator dg, HMethod methodData) {
 893 cananian 1.1.2.33         Exp mthref = new NAME(tf, source,
 894 cananian 1.1.2.48                               runtime.getNameMap().label(methodData, "obj"));
 895 cananian 1.1.2.40         //let this NAME be HClass.Void, since it points at a static object
 896 cananian 1.1.2.40         //which the gc doesn't need to know about.  If we give it a type,
 897 cananian 1.1.2.40         //then the derivation generator will get confused by derived pointers
 898 cananian 1.1.2.40         //to it, since it doesn't live in a canonical temp.
 899 cananian 1.1.2.40         /*DECLARE(dg, linker.forName("java.lang.reflect.Method"), mthref);*/
 900 cananian 1.1.2.33         return new Translation.Ex(mthref);
 901 cananian 1.1.2.3      }
 902 cananian 1.1.2.3  
 903 cananian 1.1.2.3      public Translation.Exp stringConst(TreeFactory tf, HCodeElement source,
 904 cananian 1.1.2.20                                        DerivationGenerator dg,
 905 cananian 1.1.2.3                                         String stringData) {
 906 cananian 1.1.2.3          stringSet.add(stringData);
 907 cananian 1.1.2.48         Exp strref = new NAME(tf, source, runtime.getNameMap().label(stringData));
 908 cananian 1.1.2.40         //let this NAME be HClass.Void, since it points at a static object
 909 cananian 1.1.2.40         //which the gc doesn't need to know about.  If we give it a type,
 910 cananian 1.1.2.40         //then the derivation generator will get confused by derived pointers
 911 cananian 1.1.2.40         //to it, since it doesn't live in a canonical temp.
 912 cananian 1.1.2.40         /*DECLARE(dg, linker.forName("java.lang.String"), strref);*/
 913 cananian 1.1.2.3          return new Translation.Ex(strref);
 914 cananian 1.1.2.3      }
 915 cananian 1.1.2.3  
 916 cananian 1.1.2.3      public Translation.Exp arrayBase(TreeFactory tf, HCodeElement source,
 917 cananian 1.1.2.20                                      DerivationGenerator dg,
 918 cananian 1.1.2.3                                       Translation.Exp objectref) {
 919 cananian 1.1.2.3          return new Translation.Ex
 920 cananian 1.1.2.3              (new BINOP
 921 cananian 1.1.2.3               (tf, source, Type.POINTER, Bop.ADD,
 922 cananian 1.1.2.42               PTRMASK(tf, source, dg, objectref.unEx(tf)),
 923 cananian 1.1.2.3                new CONST(tf, source, OBJ_AZERO_OFF)));
 924 cananian 1.1.2.3      }
 925 cananian 1.1.2.3      public Translation.Exp arrayOffset(TreeFactory tf, HCodeElement source,
 926 cananian 1.1.2.20                                        DerivationGenerator dg,
 927 cananian 1.1.2.3                                         HClass arrayType, Translation.Exp index)
 928 cananian 1.1.2.3      {
 929 cananian 1.3.2.1          assert arrayType.isArray();
 930 cananian 1.1.2.3          HClass compType = arrayType.getComponentType();
 931 cananian 1.1.2.3          int elementsize = POINTER_SIZE;
 932 cananian 1.1.2.3          if (compType.isPrimitive())
 933 cananian 1.1.2.3              elementsize =
 934 cananian 1.1.2.3                  (compType==HClass.Long || compType==HClass.Double) 
 935 cananian 1.1.2.3                  ? LONG_WORD_SIZE :
 936 cananian 1.1.2.3                  (compType==HClass.Int || compType==HClass.Float)
 937 cananian 1.1.2.3                  ? WORD_SIZE :
 938 cananian 1.1.2.3                  (compType==HClass.Short || compType==HClass.Char)
 939 cananian 1.1.2.3                  ? 2 : 1;
 940 cananian 1.1.2.3          return new Translation.Ex
 941 cananian 1.1.2.3              (new BINOP
 942 cananian 1.1.2.3               // should this type be POINTER or INT? [consider long arrays]
 943 cananian 1.1.2.3               (tf, source, Type.INT, Bop.MUL,
 944 cananian 1.1.2.3                index.unEx(tf),
 945 cananian 1.1.2.3                new CONST(tf, source, elementsize)));
 946 cananian 1.1.2.3      }
 947 cananian 1.1.2.3      public Translation.Exp fieldBase(TreeFactory tf, HCodeElement source,
 948 cananian 1.1.2.20                                      DerivationGenerator dg,
 949 cananian 1.1.2.3                                       Translation.Exp objectref) {
 950 cananian 1.1.2.3          return new Translation.Ex
 951 cananian 1.1.2.3              (new BINOP
 952 cananian 1.1.2.3               (tf, source, Type.POINTER, Bop.ADD,
 953 cananian 1.1.2.42               PTRMASK(tf, source, dg, objectref.unEx(tf)),
 954 cananian 1.1.2.3                new CONST(tf, source, OBJ_FZERO_OFF)));
 955 cananian 1.1.2.3      }
 956 cananian 1.1.2.3      public Translation.Exp fieldOffset(TreeFactory tf, HCodeElement source,
 957 cananian 1.1.2.20                                         DerivationGenerator dg,
 958 cananian 1.1.2.3                                         HField field) {
 959 cananian 1.3.2.1          assert !field.isStatic();
 960 cananian 1.1.2.3          return new Translation.Ex
 961 cananian 1.1.2.3              (new CONST(tf, source, cfm.fieldOffset(field)));
 962 cananian 1.1.2.3      }
 963 cananian 1.3.2.3      /** Returns a pointer to the claz structure associated with the
 964 cananian 1.3.2.3       *  given objectref. */
 965 cananian 1.3.2.3      protected Exp _claz_(TreeFactory tf, HCodeElement source,
 966 cananian 1.1.2.45                        DerivationGenerator dg,
 967 cananian 1.1.2.45                        Translation.Exp objectref) {
 968 cananian 1.1.2.45         return DECLARE(dg, HClass.Void/*claz pointer*/,
 969 cananian 1.1.2.45               new MEM
 970 cananian 1.1.2.45               (tf, source, Type.POINTER,
 971 cananian 1.1.2.45                new BINOP
 972 cananian 1.1.2.45                (tf, source, Type.POINTER, Bop.ADD,
 973 cananian 1.1.2.45                 PTRMASK(tf, source, dg, objectref.unEx(tf)),
 974 cananian 1.1.2.45                 new CONST(tf, source, OBJ_CLAZ_OFF))));
 975 cananian 1.1.2.45     }
 976 cananian 1.1.2.3      public Translation.Exp methodBase(TreeFactory tf, HCodeElement source,
 977 cananian 1.1.2.20                                         DerivationGenerator dg,
 978 cananian 1.1.2.3                                        Translation.Exp objectref) {
 979 cananian 1.1.2.3          return new Translation.Ex
 980 cananian 1.1.2.3              (new BINOP
 981 cananian 1.1.2.3               (tf, source, Type.POINTER, Bop.ADD,
 982 cananian 1.1.2.45               _claz_(tf, source, dg, objectref),
 983 cananian 1.1.2.3                new CONST(tf, source, CLAZ_METHODS_OFF)));
 984 cananian 1.1.2.3      }
 985 cananian 1.1.2.53     /* some methods are both defined in interfaces *and* inherited from
 986 cananian 1.1.2.53      * java.lang.Object.  Use the java.lang.Object version. */
 987 cananian 1.1.2.53     private HMethod remap(HMethod hm) {
 988 cananian 1.1.2.53         try {
 989 cananian 1.1.2.53             return linker.forName("java.lang.Object")
 990 cananian 1.1.2.53                 .getMethod(hm.getName(), hm.getDescriptor());
 991 cananian 1.1.2.53         } catch (NoSuchMethodError nsme) {
 992 cananian 1.1.2.53             return hm;
 993 cananian 1.1.2.53         }
 994 cananian 1.1.2.53     }
 995 cananian 1.1.2.3      public Translation.Exp methodOffset(TreeFactory tf, HCodeElement source,
 996 cananian 1.1.2.20                                         DerivationGenerator dg,
 997 cananian 1.1.2.3                                          HMethod method) {
 998 cananian 1.3.2.1          assert !method.isStatic();
 999 cananian 1.1.2.53         method = remap(method);//handle interface methods inherited from Object
1000 cananian 1.1.2.3          if (method.isInterfaceMethod()) {
1001 cananian 1.1.2.3              // use interface method map.
1002 cananian 1.1.2.3              return new Translation.Ex
1003 cananian 1.1.2.3                  (new CONST(tf, source,
1004 cananian 1.1.2.3                             CLAZ_INTERFACES_OFF - CLAZ_METHODS_OFF -
1005 cananian 1.1.2.3                             imm.methodOrder(method) * POINTER_SIZE));
1006 cananian 1.1.2.3          } else { 
1007 cananian 1.1.2.3              // use class method map.
1008 cananian 1.1.2.3              return new Translation.Ex
1009 cananian 1.1.2.3                  (new CONST(tf, source,
1010 cananian 1.1.2.3                             cmm.methodOrder(method) * POINTER_SIZE));
1011 cananian 1.1.2.1          }
1012 cananian 1.1.2.46     }
1013 cananian 1.1.2.46     public Translation.Exp referenceEqual(TreeFactory tf, HCodeElement source,
1014 cananian 1.1.2.46                                           DerivationGenerator dg,
1015 cananian 1.1.2.46                                           Translation.Exp refLeft,
1016 cananian 1.1.2.46                                           Translation.Exp refRight) {
1017 cananian 1.1.2.46         // have to do pointer masking before we can compare these references.
1018 cananian 1.1.2.46         return new Translation.Ex
1019 cananian 1.1.2.46             (new BINOP(tf, source, Type.POINTER, Bop.CMPEQ,
1020 cananian 1.1.2.46                        PTRMASK(tf, source, dg, refLeft.unEx(tf)),
1021 cananian 1.1.2.46                        PTRMASK(tf, source, dg, refRight.unEx(tf))));
1022 cananian 1.1.2.1      }
1023 cananian 1.2      }