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 }