1 cananian 1.1.2.1 // TinyClassFieldMap.java, created Fri Mar 15 19:21:30 2002 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.Backend.RuntimeTiny; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Backend.Analysis.ClassFieldMap; 7 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 8 cananian 1.1.2.1 import harpoon.ClassFile.HField; 9 cananian 1.1.2.1 10 cananian 1.1.2.1 import java.util.ArrayList; 11 cananian 1.1.2.1 import java.util.Arrays; 12 cananian 1.1.2.1 import java.util.Collections; 13 cananian 1.1.2.1 import java.util.Comparator; 14 cananian 1.1.2.1 import java.util.HashMap; 15 cananian 1.1.2.1 import java.util.Iterator; 16 cananian 1.1.2.1 import java.util.List; 17 cananian 1.1.2.1 import java.util.Map; 18 cananian 1.1.2.1 /** 19 cananian 1.1.2.1 * <code>TinyClassFieldMap</code> is an extension of <code>ClassFieldMap</code> 20 cananian 1.1.2.1 * which lays out objects *attempting* to align them, but not forcing an 21 cananian 1.1.2.1 * alignment. 22 cananian 1.1.2.1 * 23 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 24 cananian 1.3 * @version $Id: TinyClassFieldMap.java,v 1.3 2004/02/08 03:21:01 cananian Exp $ 25 cananian 1.1.2.1 */ 26 cananian 1.1.2.1 public abstract class TinyClassFieldMap extends ClassFieldMap { 27 cananian 1.1.2.2 final int first_alignment; 28 cananian 1.1.2.1 29 cananian 1.1.2.1 /** Creates a <code>TinyClassFieldMap</code>. */ 30 cananian 1.1.2.2 public TinyClassFieldMap() { this(0); } 31 cananian 1.1.2.2 /** Creates a <code>TinyClassFieldMap</code>. */ 32 cananian 1.1.2.2 public TinyClassFieldMap(int first_alignment) { 33 cananian 1.1.2.2 this.first_alignment = first_alignment; 34 cananian 1.1.2.2 } 35 cananian 1.1.2.1 36 cananian 1.1.2.1 /** Use this function to indicate a *preferred* but not *mandatory* 37 cananian 1.1.2.1 * alignment for the given field. We will "try hard" to honor this 38 cananian 1.1.2.1 * alignment, but not if it would mean increasing the object size. */ 39 cananian 1.1.2.1 public int fieldPreferredAlignment(HField hf){ return fieldAlignment(hf); } 40 cananian 1.1.2.1 41 cananian 1.1.2.1 private final Map<HClass,HField[]> cache = new HashMap<HClass,HField[]>(); 42 cananian 1.1.2.1 protected HField[] declaredFields(HClass hc) { 43 cananian 1.1.2.1 if (!cache.containsKey(hc)) { 44 cananian 1.1.2.1 // determine the alignment of the last field of the superclass. 45 cananian 1.1.2.2 int alignment=first_alignment; 46 cananian 1.1.2.1 HClass sc = hc.getSuperclass(); 47 cananian 1.1.2.1 if (sc!=null) { 48 cananian 1.1.2.1 List<HField> l = fieldList(sc); 49 cananian 1.1.2.1 if (l.size()>0) { 50 cananian 1.1.2.1 HField lastfield = l.get(l.size()-1); 51 cananian 1.1.2.1 alignment = fieldOffset(lastfield)+fieldSize(lastfield); 52 cananian 1.1.2.1 } 53 cananian 1.1.2.1 } 54 cananian 1.1.2.1 // make list of non-static fields. 55 cananian 1.1.2.1 List<HField> l = 56 cananian 1.1.2.1 new ArrayList<HField>(Arrays.asList(hc.getDeclaredFields())); 57 cananian 1.1.2.1 for (Iterator<HField> it=l.iterator(); it.hasNext(); ) 58 cananian 1.1.2.1 if (it.next().isStatic()) 59 cananian 1.1.2.1 it.remove(); 60 cananian 1.1.2.1 // sort declared fields by max(preferredalignment,alignment,size) 61 cananian 1.1.2.1 // (largest first) 62 cananian 1.1.2.1 Collections.sort(l, new Comparator<HField>() { 63 cananian 1.1.2.1 public int compare(HField hf1, HField hf2) { 64 cananian 1.1.2.1 int align1 = Math.max(fieldPreferredAlignment(hf1), 65 cananian 1.1.2.1 fieldAlignment(hf1)); 66 cananian 1.1.2.1 int align2 = Math.max(fieldPreferredAlignment(hf2), 67 cananian 1.1.2.1 fieldAlignment(hf2)); 68 cananian 1.1.2.1 return Math.max(fieldSize(hf2),align2) 69 cananian 1.1.2.1 - Math.max(fieldSize(hf1),align1); 70 cananian 1.1.2.1 } 71 cananian 1.1.2.1 }); 72 cananian 1.1.2.1 // make our result list 73 cananian 1.1.2.1 List<HField> result = new ArrayList<HField>(l.size()); 74 cananian 1.1.2.1 // while we have more fields to order: 75 cananian 1.1.2.1 while (!l.isEmpty()) { 76 cananian 1.1.2.1 HField selectedField = null; 77 cananian 1.1.2.1 // find the largest aligned *must-align* field. 78 cananian 1.1.2.1 // (a must-align field has fieldAlignment>1) 79 cananian 1.1.2.1 for (Iterator<HField> it=l.iterator(); 80 cananian 1.1.2.1 selectedField==null && it.hasNext(); ) { 81 cananian 1.1.2.1 HField hf = it.next(); 82 cananian 1.1.2.2 // hack to skip fields which cross the header boundary 83 cananian 1.1.2.2 if (alignment<0 && alignment+fieldSize(hf)>0) continue; 84 cananian 1.1.2.1 if (fieldAlignment(hf) > 1 && 85 cananian 1.1.2.1 0 == (alignment % fieldAlignment(hf))) { 86 cananian 1.1.2.1 selectedField = hf; 87 cananian 1.1.2.1 it.remove(); 88 cananian 1.1.2.1 } 89 cananian 1.1.2.1 } 90 cananian 1.1.2.1 // else, find the largest preferably-aligned field. 91 cananian 1.1.2.1 for (Iterator<HField> it=l.iterator(); 92 cananian 1.1.2.1 selectedField==null && it.hasNext(); ) { 93 cananian 1.1.2.1 HField hf = it.next(); 94 cananian 1.1.2.2 // hack to skip fields which cross the header boundary 95 cananian 1.1.2.2 if (alignment<0 && alignment+fieldSize(hf)>0) continue; 96 cananian 1.1.2.1 if (0 == (alignment % fieldPreferredAlignment(hf))) { 97 cananian 1.1.2.1 selectedField = hf; 98 cananian 1.1.2.1 it.remove(); 99 cananian 1.1.2.1 } 100 cananian 1.1.2.1 } 101 cananian 1.1.2.1 // otherwise find the smallest unaligned field. 102 cananian 1.1.2.1 if (selectedField==null) 103 cananian 1.1.2.1 selectedField = l.remove(l.size()-1); 104 cananian 1.1.2.2 // hack to protect the header boundary. 105 cananian 1.1.2.2 if (alignment<0 && alignment+fieldSize(selectedField)>0) 106 cananian 1.1.2.2 alignment=0; 107 cananian 1.1.2.1 // okay, add the selected field to the result, update alignment 108 cananian 1.1.2.1 result.add(selectedField); 109 cananian 1.1.2.1 while (0 != (alignment % fieldAlignment(selectedField))) 110 cananian 1.1.2.1 alignment++; 111 cananian 1.1.2.1 alignment += fieldSize(selectedField); 112 cananian 1.1.2.1 } 113 cananian 1.1.2.1 // done. 114 cananian 1.1.2.1 cache.put(hc, result.toArray(new HField[result.size()])); 115 cananian 1.1.2.1 } 116 cananian 1.1.2.1 return cache.get(hc); 117 cananian 1.1.2.1 } 118 cananian 1.1.2.2 // XXX copied from superclass, but hacked to deal with first_alignment. 119 cananian 1.1.2.2 public int fieldOffset(HField hf) { 120 cananian 1.1.2.2 assert hf!=null && !hf.isStatic(); 121 cananian 1.1.2.2 if (!cache2.containsKey(hf)) { 122 cananian 1.1.2.2 int offset=first_alignment; 123 cananian 1.3 for (HField nexthf : fieldList(hf.getDeclaringClass())) { 124 cananian 1.1.2.2 // hack to protect the header boundary 125 cananian 1.1.2.2 if (offset<0 && offset+fieldSize(nexthf)>0) 126 cananian 1.1.2.2 offset=0; 127 cananian 1.1.2.2 // end hack 128 cananian 1.1.2.2 int align = fieldAlignment(nexthf); 129 cananian 1.1.2.2 assert align>0; 130 cananian 1.1.2.2 if ((offset % align) != 0) 131 cananian 1.1.2.2 offset += align - (offset%align); 132 cananian 1.1.2.2 assert (offset % align) == 0; 133 cananian 1.1.2.2 if (!cache2.containsKey(nexthf)) 134 cananian 1.1.2.2 cache2.put(nexthf, new Integer(offset)); 135 cananian 1.1.2.2 offset+=fieldSize(nexthf); 136 cananian 1.1.2.2 } 137 cananian 1.1.2.2 } 138 cananian 1.1.2.2 assert cache2.containsKey(hf) : hf+" not in fieldList()"; 139 cananian 1.1.2.2 return cache2.get(hf).intValue(); 140 cananian 1.1.2.2 } 141 cananian 1.1.2.2 private final Map<HField,Integer> cache2 = new HashMap<HField,Integer>(); 142 cananian 1.2 }