1 cananian 1.1.2.1 // BitFieldNumbering.java, created Sun Mar  4 20:21:45 2001 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 2000 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.Analysis.Transactions;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  7 cananian 1.1.2.1 import harpoon.ClassFile.HClassMutator;
  8 cananian 1.1.2.1 import harpoon.ClassFile.HField;
  9 cananian 1.1.2.2 import harpoon.ClassFile.Linker;
 10 cananian 1.1.2.1 import harpoon.Util.Util;
 11 cananian 1.5     import java.util.Collections;
 12 cananian 1.5     import java.util.HashSet;
 13 cananian 1.1.2.1 import java.util.HashMap;
 14 cananian 1.1.2.1 import java.util.Map;
 15 cananian 1.5     import java.util.Set;
 16 cananian 1.1.2.1 
 17 cananian 1.1.2.1 /**
 18 cananian 1.1.2.1  * <code>BitFieldNumbering</code> finds a bit-position and a field to
 19 cananian 1.1.2.1  * embed boolean flags describing object fields.
 20 cananian 1.1.2.1  * 
 21 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 22 cananian 1.5      * @version $Id: BitFieldNumbering.java,v 1.5 2003/07/21 21:21:49 cananian Exp $
 23 cananian 1.1.2.1  */
 24 cananian 1.1.2.2 public class BitFieldNumbering {
 25 cananian 1.1.2.1     // note: for 64-bit archs, might be worthwhile to make fields 64 bits.
 26 cananian 1.1.2.1     public static final HClass FIELD_TYPE = HClass.Int;
 27 cananian 1.1.2.1     public static final int BITS_IN_FIELD = 32;
 28 cananian 1.1.2.1 
 29 cananian 1.1.2.1     // unique suffix for the fields created by this BitFieldNumbering.
 30 cananian 1.1.2.1     private final String suffix;
 31 cananian 1.1.2.2     // cache HClass for java.lang.Object
 32 cananian 1.1.2.2     private final HClass HCobject;
 33 cananian 1.5         // set of all referenced 'bitfield' fields: mutable version.
 34 cananian 1.5         private final Set<HField> _bitfields = new HashSet<HField>();
 35 cananian 1.5         /** Set of all fields returned as part of a <code>BitFieldTuple</code>
 36 cananian 1.5          *  by <code>bfLoc</code> or <code>arrayBitField</code>. */
 37 cananian 1.5         public final Set<HField> bitfields =
 38 cananian 1.5             Collections.unmodifiableSet(_bitfields);
 39 cananian 1.1.2.1 
 40 cananian 1.1.2.1     /** Creates a <code>BitFieldNumbering</code>. */
 41 cananian 1.1.2.2     public BitFieldNumbering(Linker l) { this(l, ""); }
 42 cananian 1.1.2.2     public BitFieldNumbering(Linker l, String suffix) {
 43 cananian 1.1.2.2         this.suffix=suffix;
 44 cananian 1.1.2.2         this.HCobject = l.forName("java.lang.Object");
 45 cananian 1.1.2.2     }
 46 cananian 1.1.2.1 
 47 cananian 1.1.2.2     public static class BitFieldTuple {
 48 cananian 1.1.2.2         public final HField field;
 49 cananian 1.1.2.2         public final int bit;
 50 cananian 1.1.2.1         BitFieldTuple(HField field, int bit) {this.field=field; this.bit=bit;}
 51 cananian 1.1.2.1         public String toString() { return "Bit "+bit+" of "+field; }
 52 cananian 1.1.2.1     }
 53 cananian 1.1.2.1     public BitFieldTuple bfLoc(HField hf) {
 54 cananian 1.1.2.1         int n = fieldNumber(hf);
 55 cananian 1.1.2.1         // which class would the check field belong to?
 56 cananian 1.1.2.2         // answer: same class as contains the definition of field #(marker)
 57 cananian 1.1.2.1         int marker = BITS_IN_FIELD * (n/BITS_IN_FIELD);
 58 cananian 1.1.2.1         HClass hc = hf.getDeclaringClass();
 59 cananian 1.1.2.2         if (marker!=0) {
 60 cananian 1.1.2.2             while (classNumber(hc.getSuperclass()) > marker)
 61 cananian 1.1.2.2                 hc = hc.getSuperclass();
 62 cananian 1.1.2.2         } else {
 63 cananian 1.1.2.2             /* special case: zero'th field goes in java.lang.Object.
 64 cananian 1.1.2.2              * this is to make the array case more regular. */
 65 cananian 1.1.2.2             hc = HCobject;
 66 cananian 1.1.2.2         }
 67 cananian 1.1.2.1         // okay, fetch this field, creating if necessary.
 68 cananian 1.1.2.1         HField bff = getOrMake(hc, n/BITS_IN_FIELD);
 69 cananian 1.1.2.1         // done.
 70 cananian 1.1.2.1         return new BitFieldTuple(bff, n % BITS_IN_FIELD);
 71 cananian 1.1.2.1     }
 72 cananian 1.1.2.1     public HField arrayBitField(HClass hc) {
 73 cananian 1.3.2.1         assert hc.isArray();
 74 cananian 1.1.2.2         /* okay, first 'field info' field is used for arrays. */
 75 cananian 1.1.2.2         return getOrMake(HCobject, 0);
 76 cananian 1.1.2.1     }
 77 cananian 1.1.2.1 
 78 cananian 1.1.2.1     // fetch a bitfield, creating if necessary.
 79 cananian 1.1.2.1     private HField getOrMake(HClass where, int which) {
 80 cananian 1.1.2.2         /* for safety: always call classNumber(where) to cache the field
 81 cananian 1.1.2.2          * numbering for 'where' *before* we screw it up by adding fields. */
 82 cananian 1.1.2.2         classNumber(where);
 83 cananian 1.1.2.2         /* okay, now fetch/make the bitfield field. */
 84 cananian 1.1.2.1         String fieldname="$$bitfield"+which+suffix;
 85 cananian 1.1.2.1         try {
 86 cananian 1.1.2.1             return where.getDeclaredField(fieldname);
 87 cananian 1.1.2.1         } catch (NoSuchFieldError nsfe) {
 88 cananian 1.5                 HField hf =
 89 cananian 1.5                     where.getMutator().addDeclaredField(fieldname, FIELD_TYPE);
 90 cananian 1.5                 _bitfields.add(hf);
 91 cananian 1.5                 return hf;
 92 cananian 1.1.2.1         }
 93 cananian 1.1.2.1     }
 94 cananian 1.1.2.1     // field numbering.
 95 cananian 1.5         final Map<HField,Integer> fieldNumbers = new HashMap<HField,Integer>();
 96 cananian 1.5         final Map<HClass,Integer> classNumbers = new HashMap<HClass,Integer>();
 97 cananian 1.1.2.1     private int fieldNumber(HField hf) {
 98 cananian 1.3.2.1         assert !hf.isStatic();
 99 cananian 1.3.2.1         assert !hf.getDeclaringClass().isInterface();
100 cananian 1.1.2.1         if (!fieldNumbers.containsKey(hf))
101 cananian 1.1.2.1             classNumber(hf.getDeclaringClass());
102 cananian 1.5             assert fieldNumbers.containsKey(hf) : hf + " / "+fieldNumbers;
103 cananian 1.5             return fieldNumbers.get(hf).intValue();
104 cananian 1.1.2.1     }
105 cananian 1.1.2.2     /* all fields in 'hc' are numbered *strictly less than* classNumber(hc) */
106 cananian 1.1.2.1     private int classNumber(HClass hc) {
107 cananian 1.3.2.1         assert !hc.isArray();
108 cananian 1.3.2.1         assert !hc.isInterface();
109 cananian 1.1.2.1         if (!classNumbers.containsKey(hc)) {
110 cananian 1.1.2.1             HClass sc = hc.getSuperclass();
111 cananian 1.1.2.1             int start = (sc==null) ? 0 : classNumber(sc);
112 cananian 1.1.2.1             HField[] hfa = hc.getDeclaredFields();
113 cananian 1.1.2.1             for (int i=0; i<hfa.length; i++)
114 cananian 1.1.2.1                 if (!hfa[i].isStatic())
115 cananian 1.1.2.1                     fieldNumbers.put(hfa[i], new Integer(start++));
116 cananian 1.1.2.1             classNumbers.put(hc, new Integer(start));
117 cananian 1.1.2.1         }
118 cananian 1.5             return classNumbers.get(hc).intValue();
119 cananian 1.1.2.1     }
120 cananian 1.2     }