1 cananian 1.1.4.1 // ClassFieldMap.java, created Sun Oct 10 19:30:33 1999 by cananian 2 cananian 1.1.4.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.4.1 package harpoon.Backend.Analysis; 5 cananian 1.1.4.1 6 cananian 1.1.4.1 import harpoon.ClassFile.HClass; 7 cananian 1.1.4.1 import harpoon.ClassFile.HField; 8 cananian 1.1.4.1 import harpoon.Util.HClassUtil; 9 cananian 1.6 import net.cscott.jutil.UnmodifiableListIterator; 10 cananian 1.1.4.1 import harpoon.Util.Util; 11 cananian 1.1.4.1 12 cananian 1.1.4.1 import java.util.AbstractSequentialList; 13 cananian 1.1.4.1 import java.util.HashMap; 14 cananian 1.1.4.1 import java.util.Iterator; 15 cananian 1.1.4.1 import java.util.List; 16 cananian 1.1.4.1 import java.util.ListIterator; 17 cananian 1.1.4.1 import java.util.Map; 18 cananian 1.1.4.1 import java.util.NoSuchElementException; 19 cananian 1.1.4.1 /** 20 cananian 1.1.4.1 * A <code>ClassFieldMap</code> is a <code>FieldMap</code> for 21 cananian 1.1.4.1 * non-static fields of a class. The user must implement a function 22 cananian 1.1.4.1 * giving the size of a field to complete the implementation. 23 cananian 1.1.4.1 * Results are cached for efficiency. 24 cananian 1.1.4.1 * 25 cananian 1.1.4.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 26 cananian 1.7 * @version $Id: ClassFieldMap.java,v 1.7 2004/02/08 03:20:42 cananian Exp $ 27 cananian 1.1.4.1 */ 28 cananian 1.1.4.1 public abstract class ClassFieldMap extends harpoon.Backend.Maps.FieldMap { 29 cananian 1.1.4.1 /** Creates a <code>ClassFieldMap</code>. */ 30 cananian 1.1.4.1 public ClassFieldMap() { /* no special initialization. */ } 31 cananian 1.1.4.2 32 cananian 1.1.4.1 // caching version of method inherited from superclass. 33 cananian 1.1.4.1 public int fieldOffset(HField hf) { 34 cananian 1.3.2.1 assert hf!=null && !hf.isStatic(); 35 cananian 1.1.4.1 if (!cache.containsKey(hf)) { 36 cananian 1.1.4.1 int offset=0; 37 cananian 1.7 for (HField nexthf : fieldList(hf.getDeclaringClass())) { 38 cananian 1.1.4.2 int align = fieldAlignment(nexthf); 39 cananian 1.3.2.1 assert align>0; 40 cananian 1.1.4.2 if ((offset % align) != 0) 41 cananian 1.1.4.2 offset += align - (offset%align); 42 cananian 1.3.2.1 assert (offset % align) == 0; 43 cananian 1.1.4.1 if (!cache.containsKey(nexthf)) 44 cananian 1.1.4.1 cache.put(nexthf, new Integer(offset)); 45 cananian 1.1.4.1 offset+=fieldSize(nexthf); 46 cananian 1.1.4.1 } 47 cananian 1.1.4.1 } 48 cananian 1.3.2.1 assert cache.containsKey(hf) : hf+" not in fieldList()"; 49 cananian 1.3.2.2 return cache.get(hf).intValue(); 50 cananian 1.1.4.1 } 51 cananian 1.3.2.2 private final Map<HField,Integer> cache = new HashMap<HField,Integer>(); 52 cananian 1.1.4.1 53 cananian 1.1.4.1 // the meat of this class: return non-static fields in order, from 54 cananian 1.1.4.1 // top-most superclass down. 55 cananian 1.3.2.2 public List<HField> fieldList(final HClass hc) { 56 cananian 1.3.2.1 assert hc!=null; 57 cananian 1.1.4.1 // first calculate size of list. 58 cananian 1.1.4.1 int n=0; 59 cananian 1.1.4.1 for (HClass hcp=hc; hcp!=null; hcp=hcp.getSuperclass()) { 60 cananian 1.1.4.3 HField[] fields = declaredFields(hcp); 61 cananian 1.1.4.1 for (int i=0; i<fields.length; i++) 62 cananian 1.1.4.1 if (!fields[i].isStatic()) n++; 63 cananian 1.1.4.1 } 64 cananian 1.1.4.1 final int size = n; 65 cananian 1.1.4.1 // now make & return list object. 66 cananian 1.3.2.2 return new AbstractSequentialList<HField>() { 67 cananian 1.1.4.1 public int size() { return size; } 68 cananian 1.3.2.2 public ListIterator<HField> listIterator(final int index) { 69 cananian 1.3.2.2 return new UnmodifiableListIterator<HField>() { 70 cananian 1.1.4.1 final HClass[] parents = HClassUtil.parents(hc); 71 cananian 1.1.4.1 HField[] fields; 72 cananian 1.1.4.1 int pindex, findex, xindex; 73 cananian 1.1.4.1 boolean done=true, forwards; 74 cananian 1.1.4.1 { // initialization code: count from beginning or end 75 cananian 1.1.4.1 // depending on which is closer. 76 cananian 1.1.4.1 if (index < size/2) { // count from beginning. 77 cananian 1.1.4.1 pindex=0; 78 cananian 1.1.4.3 fields = declaredFields(parents[pindex]); 79 cananian 1.1.4.1 findex=-1; forwards=true; 80 cananian 1.1.4.1 for (xindex=-1; xindex < index; xindex++) 81 cananian 1.1.4.1 advance(); 82 cananian 1.1.4.1 } else { // count from end. 83 cananian 1.1.4.1 pindex = parents.length-1; 84 cananian 1.1.4.3 fields = declaredFields(parents[pindex]); 85 cananian 1.1.4.1 findex=fields.length; forwards=true; 86 cananian 1.1.4.1 for (xindex=size; xindex > index; xindex--) 87 cananian 1.1.4.1 retreat(); 88 cananian 1.1.4.1 } 89 cananian 1.1.4.1 } 90 cananian 1.1.4.1 public boolean hasNext() { 91 cananian 1.1.4.1 if (!forwards) changeDirection(); 92 cananian 1.1.4.1 return !done; 93 cananian 1.1.4.1 } 94 cananian 1.1.4.1 public boolean hasPrevious() { 95 cananian 1.1.4.1 if (forwards) changeDirection(); 96 cananian 1.1.4.1 return !done; 97 cananian 1.1.4.1 } 98 cananian 1.3.2.2 public HField next() { 99 cananian 1.1.4.1 if (!forwards) changeDirection(); 100 cananian 1.1.4.1 if (done) throw new NoSuchElementException(); 101 cananian 1.1.4.1 xindex++; 102 cananian 1.1.4.1 HField hf = fields[findex]; advance(); return hf; 103 cananian 1.1.4.1 } 104 cananian 1.3.2.2 public HField previous() { 105 cananian 1.1.4.1 if (forwards) changeDirection(); 106 cananian 1.1.4.1 if (done) throw new NoSuchElementException(); 107 cananian 1.1.4.1 xindex--; 108 cananian 1.1.4.1 HField hf = fields[findex]; retreat(); return hf; 109 cananian 1.1.4.1 } 110 cananian 1.1.4.1 public int nextIndex() { return xindex; } 111 cananian 1.1.4.1 private void advance() { 112 cananian 1.1.4.1 done=false; 113 cananian 1.1.4.1 while (true) { 114 cananian 1.1.4.1 for (findex++; findex < fields.length; findex++) 115 cananian 1.1.4.1 if (!fields[findex].isStatic()) return; 116 cananian 1.1.4.1 if (++pindex >= parents.length) break; 117 cananian 1.1.4.3 fields = declaredFields(parents[pindex]); 118 cananian 1.1.4.1 findex = -1; 119 cananian 1.1.4.1 } 120 cananian 1.1.4.1 --pindex; done=true; 121 cananian 1.1.4.1 } 122 cananian 1.1.4.1 private void retreat() { 123 cananian 1.1.4.1 done=false; 124 cananian 1.1.4.1 while (true) { 125 cananian 1.1.4.1 for (findex--; findex >= 0; findex--) 126 cananian 1.1.4.1 if (!fields[findex].isStatic()) return; 127 cananian 1.1.4.1 if (--pindex < 0) break; 128 cananian 1.1.4.3 fields = declaredFields(parents[pindex]); 129 cananian 1.1.4.1 findex = fields.length; 130 cananian 1.1.4.1 } 131 cananian 1.1.4.1 ++pindex; done=true; 132 cananian 1.1.4.1 } 133 cananian 1.1.4.1 private void changeDirection() { 134 cananian 1.1.4.1 if (forwards) retreat(); else advance(); 135 cananian 1.1.4.1 forwards = !forwards; 136 cananian 1.1.4.1 } 137 cananian 1.1.4.1 }; 138 cananian 1.1.4.1 } 139 cananian 1.1.4.1 }; 140 cananian 1.1.4.3 } 141 cananian 1.1.4.3 /** Return the declared fields of the specified class in the 142 cananian 1.1.4.3 * order in which they should be allocated. This implementation 143 cananian 1.1.4.3 * just returns the result of <code>hc.getDeclaredFields()</code>, 144 cananian 1.1.4.3 * but you can override this to use a more intelligent sorting 145 cananian 1.1.4.3 * routine to save space. You do not have to filter static methods 146 cananian 1.1.4.3 * out of the returned array, but you may if you like. */ 147 cananian 1.1.4.3 protected HField[] declaredFields(HClass hc) { 148 cananian 1.1.4.3 return hc.getDeclaredFields(); 149 cananian 1.1.4.1 } 150 cananian 1.2 }