1 cananian 1.1.2.1 // DataReflection2.java, created Sat Oct 16 15:48:14 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.1 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Backend.Generic.Frame; 8 cananian 1.1.2.1 import harpoon.Backend.Maps.NameMap; 9 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 10 cananian 1.1.2.2 import harpoon.ClassFile.HConstructor; 11 cananian 1.1.2.1 import harpoon.ClassFile.HDataElement; 12 cananian 1.1.2.2 import harpoon.ClassFile.HField; 13 cananian 1.1.2.2 import harpoon.ClassFile.HMember; 14 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 15 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 16 cananian 1.1.2.1 import harpoon.IR.Tree.TreeFactory; 17 cananian 1.1.2.3 import harpoon.IR.Tree.ALIGN; 18 cananian 1.1.2.2 import harpoon.IR.Tree.CONST; 19 cananian 1.1.2.1 import harpoon.IR.Tree.LABEL; 20 cananian 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 21 cananian 1.1.2.1 import harpoon.Temp.Label; 22 cananian 1.1.2.1 23 cananian 1.1.2.2 import java.lang.reflect.Modifier; 24 cananian 1.1.2.1 import java.util.ArrayList; 25 cananian 1.1.2.2 import java.util.Arrays; 26 cananian 1.1.2.2 import java.util.Collections; 27 cananian 1.1.2.2 import java.util.Comparator; 28 cananian 1.1.2.2 import java.util.Iterator; 29 cananian 1.1.2.1 import java.util.List; 30 cananian 1.1.2.1 /** 31 cananian 1.1.2.1 * <code>DataReflection2</code> generates class information tables 32 cananian 1.1.2.1 * for each class, with lots of juicy information needed by JNI and 33 cananian 1.1.2.1 * java language reflection. The class information table includes: 34 cananian 1.1.2.1 * <UL> 35 cananian 1.1.2.1 * <LI>A pointer to a UTF-8 encoded string naming the class. 36 cananian 1.1.2.1 * <LI>A pointer to the claz structure containing the dispatch 37 cananian 1.1.2.1 * tables & etc. (See <code>DataClaz</code>.) 38 cananian 1.1.2.12 * <LI>The java access modifiers of the class. 39 cananian 1.1.2.1 * <LI>A sorted map of member signatures to method and field offsets. 40 cananian 1.1.2.1 * </UL> 41 cananian 1.1.2.1 * 42 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 43 cananian 1.6 * @version $Id: DataReflection2.java,v 1.6 2004/02/08 03:20:58 cananian Exp $ 44 cananian 1.1.2.1 */ 45 cananian 1.1.2.1 public class DataReflection2 extends Data { 46 cananian 1.1.2.1 final TreeBuilder m_tb; 47 cananian 1.1.2.1 final NameMap m_nm; 48 cananian 1.4 final boolean pointersAreLong; 49 cananian 1.1.2.1 50 cananian 1.1.2.1 /** Creates a <code>DataReflection2</code>. */ 51 cananian 1.4 public DataReflection2(Frame f, HClass hc, ClassHierarchy ch) { 52 cananian 1.1.2.1 super("reflection-data-2", hc, f); 53 cananian 1.1.2.13 this.m_nm = f.getRuntime().getNameMap(); 54 cananian 1.1.2.13 this.m_tb = (TreeBuilder) f.getRuntime().getTreeBuilder(); 55 cananian 1.4 this.pointersAreLong = f.pointersAreLong(); 56 cananian 1.1.2.1 this.root = build(hc, ch); 57 cananian 1.1.2.1 } 58 cananian 1.1.2.1 private HDataElement build(HClass hc, ClassHierarchy ch) { 59 cananian 1.1.2.2 List members = sortedMembers(hc); 60 cananian 1.5 int ptrsz = pointersAreLong ? 8 : 4; 61 cananian 1.1.2.2 62 cananian 1.1.2.2 List stmlist = new ArrayList(6+7*members.size()/* at least*/); 63 cananian 1.1.2.1 stmlist.add(new SEGMENT(tf, null, SEGMENT.REFLECTION_DATA)); 64 cananian 1.5 stmlist.add(new ALIGN(tf, null, ptrsz));// align table to word boundary 65 cananian 1.1.2.1 stmlist.add(new LABEL(tf, null, m_nm.label(hc, "classinfo"), true)); 66 cananian 1.1.2.1 // first field: a claz structure pointer. 67 cananian 1.1.2.7 stmlist.add(_DATUM(m_nm.label(hc))); 68 cananian 1.1.2.1 // next, a name string pointer. 69 cananian 1.1.2.7 stmlist.add(_DATUM(m_nm.label(hc, "namestr"))); 70 cananian 1.1.2.12 // the java access modifiers for this class 71 cananian 1.1.2.12 stmlist.add(_DATUM(new CONST(tf, null, hc.getModifiers()))); 72 cananian 1.4 // padding for 64-bit platforms. 73 cananian 1.4 if (pointersAreLong) 74 cananian 1.4 stmlist.add(_DATUM(new CONST(tf, null, 0))); 75 cananian 1.1.2.2 // pointer to the end of the lookup table. 76 cananian 1.1.2.7 stmlist.add(_DATUM(m_nm.label(hc, "classinfo_end"))); 77 cananian 1.1.2.2 // okay, now the sorted name, desc, offset table. 78 cananian 1.6 for (Object hmO : members) { 79 cananian 1.6 HMember hm = (HMember) hmO; 80 cananian 1.1.2.2 if (hm instanceof HMethod && !ch.callableMethods().contains(hm)) 81 cananian 1.1.2.2 continue; // skip uncallable methods. 82 cananian 1.1.2.10 if (hm.getDeclaringClass().equals(hc))//member info for decl'd only 83 cananian 1.1.2.10 stmlist.add(new LABEL(tf, null, memberLabel(hm,"info"), true)); 84 cananian 1.1.2.7 stmlist.add(_DATUM(memberLabel(hm, "namestr"))); 85 cananian 1.1.2.7 stmlist.add(_DATUM(memberLabel(hm, "descstr"))); 86 cananian 1.1.2.11 stmlist.add(_DATUM(memberLabel(hm, "reflectinfo"))); 87 cananian 1.1.2.2 if (!memberVirtual(hm)) 88 cananian 1.1.2.7 stmlist.add(_DATUM(memberLabel(hm, null))); 89 cananian 1.1.2.2 else if (pointersAreLong) 90 cananian 1.1.2.7 stmlist.add(_DATUM(new CONST(tf, null,(long)memberOffset(hm)))); 91 cananian 1.1.2.2 else 92 cananian 1.1.2.7 stmlist.add(_DATUM(new CONST(tf, null,(int) memberOffset(hm)))); 93 cananian 1.1.2.4 // count number of argument words for methods 94 cananian 1.1.2.4 emitNargs(stmlist, hm); 95 cananian 1.1.2.2 } 96 cananian 1.1.2.2 // ok, mark the end of the table. 97 cananian 1.1.2.2 stmlist.add(new LABEL(tf, null, 98 cananian 1.1.2.2 m_nm.label(hc, "classinfo_end"), false)); 99 cananian 1.3 // We need to put something after the label to keep gcc from 100 cananian 1.3 // moving classinfo_end into the .bss section when compiling with 101 cananian 1.3 // the PreciseC backend. 102 cananian 1.3 stmlist.add(_DATUM(m_nm.label(hc, "classinfo_end"))); 103 cananian 1.1.2.2 // now make the actual string data bits. 104 cananian 1.1.2.2 // (only for members we actually declare) 105 cananian 1.6 for (Object hmO : members) { 106 cananian 1.6 HMember hm = (HMember) hmO; 107 cananian 1.1.2.2 if (hm instanceof HMethod && !ch.callableMethods().contains(hm)) 108 cananian 1.1.2.2 continue; // skip uncallable methods. 109 cananian 1.1.2.2 // only make string data for the members we declare 110 cananian 1.1.2.2 if (hm.getDeclaringClass() != hc) continue; 111 cananian 1.1.2.2 // first name string. 112 cananian 1.1.2.8 stmlist.add(new LABEL(tf, null, memberLabel(hm,"namestr"), true)); 113 cananian 1.1.2.6 stmlist.add(emitUtf8String(hm.getName())); 114 cananian 1.1.2.2 // then descriptor string. 115 cananian 1.1.2.8 stmlist.add(new LABEL(tf, null, memberLabel(hm,"descstr"), true)); 116 cananian 1.1.2.6 stmlist.add(emitUtf8String(hm.getDescriptor())); 117 cananian 1.1.2.2 } 118 cananian 1.1.2.3 // pad out to full word after last string bit. 119 cananian 1.5 stmlist.add(new ALIGN(tf, null, ptrsz)); 120 cananian 1.1.2.2 // done, yay, whee. 121 cananian 1.1.2.1 return (HDataElement) Stm.toStm(stmlist); 122 cananian 1.1.2.2 } 123 cananian 1.1.2.2 private boolean memberVirtual(HMember hmf) { 124 cananian 1.1.2.2 if (hmf instanceof HField) return !((HField)hmf).isStatic(); 125 cananian 1.1.2.2 HMethod hm = (HMethod) hmf; 126 cananian 1.1.2.2 if (hm instanceof HConstructor) return false; 127 cananian 1.1.2.2 if (hm.isStatic()) return false; 128 cananian 1.1.2.2 if (Modifier.isPrivate(hm.getModifiers())) return false; 129 cananian 1.1.2.2 return true; 130 cananian 1.1.2.2 } 131 cananian 1.1.2.2 private Label memberLabel(HMember hm, String suffix) { 132 cananian 1.1.2.2 if (hm instanceof HField) 133 cananian 1.1.2.2 return m_nm.label((HField)hm, suffix); 134 cananian 1.1.2.2 else return m_nm.label((HMethod)hm, suffix); 135 cananian 1.1.2.2 } 136 cananian 1.1.2.14 /* some methods are both defined in interfaces *and* inherited from 137 cananian 1.1.2.14 * java.lang.Object. Use the java.lang.Object version. */ 138 cananian 1.1.2.14 private HMethod remap(HMethod hm) { 139 cananian 1.1.2.14 try { 140 cananian 1.1.2.14 return linker.forName("java.lang.Object") 141 cananian 1.1.2.14 .getMethod(hm.getName(), hm.getDescriptor()); 142 cananian 1.1.2.14 } catch (NoSuchMethodError nsme) { 143 cananian 1.1.2.14 return hm; 144 cananian 1.1.2.14 } 145 cananian 1.1.2.14 } 146 cananian 1.1.2.2 private int memberOffset(HMember hmf) { 147 cananian 1.1.2.2 if (hmf instanceof HField) 148 cananian 1.1.2.5 return m_tb.OBJ_FZERO_OFF + m_tb.cfm.fieldOffset((HField)hmf); 149 cananian 1.1.2.14 HMethod hm = remap((HMethod) hmf); 150 cananian 1.1.2.5 if (hm.isInterfaceMethod()) 151 cananian 1.1.2.5 return m_tb.CLAZ_INTERFACES_OFF - 152 cananian 1.1.2.5 m_tb.POINTER_SIZE * m_tb.imm.methodOrder(hm); 153 cananian 1.1.2.5 // virtual method 154 cananian 1.1.2.5 return m_tb.CLAZ_METHODS_OFF + 155 cananian 1.1.2.5 m_tb.POINTER_SIZE * m_tb.cmm.methodOrder(hm); 156 cananian 1.1.2.4 } 157 cananian 1.1.2.4 private void emitNargs(List stmlist, HMember hmf) { 158 cananian 1.1.2.4 final int REGS_PER_WORD = 1; 159 cananian 1.1.2.4 final int REGS_PER_DOUBLEWORD = (pointersAreLong) ? 1 : 2; 160 cananian 1.1.2.4 final int REGS_PER_POINTER = 1; 161 cananian 1.1.2.4 162 cananian 1.1.2.4 int nargs=0; 163 cananian 1.1.2.4 if (hmf instanceof HMethod) { 164 cananian 1.1.2.4 if (!((HMethod)hmf).isStatic()) nargs+=REGS_PER_POINTER; 165 cananian 1.1.2.4 String desc=hmf.getDescriptor(); 166 cananian 1.1.2.4 for (int i=1; desc.charAt(i)!=')'; i++) { // skip leading '(' 167 cananian 1.1.2.4 switch (desc.charAt(i)) { 168 cananian 1.1.2.4 case 'B': case 'C': case 'F': case 'I': case 'S': case 'Z': 169 cananian 1.1.2.4 nargs+=REGS_PER_WORD; break; 170 cananian 1.1.2.4 case 'J': case 'D': 171 cananian 1.1.2.4 nargs+=REGS_PER_DOUBLEWORD; break; 172 cananian 1.1.2.4 case 'L': 173 cananian 1.1.2.4 nargs+=REGS_PER_POINTER; 174 cananian 1.1.2.4 i=desc.indexOf(';', i); break; 175 cananian 1.1.2.4 case '[': 176 cananian 1.1.2.4 nargs+=REGS_PER_POINTER; 177 cananian 1.1.2.4 do { i++; } while (desc.charAt(i)=='['); 178 cananian 1.1.2.4 if (desc.charAt(i)=='L') i=desc.indexOf(';',i); 179 cananian 1.1.2.4 break; 180 cananian 1.1.2.4 default: 181 cananian 1.1.2.4 throw new Error("Illegal signature: "+desc); 182 cananian 1.1.2.4 } 183 cananian 1.1.2.4 } 184 cananian 1.1.2.4 } 185 cananian 1.1.2.4 // output nargs value. 186 cananian 1.1.2.4 if (pointersAreLong) 187 cananian 1.1.2.7 stmlist.add(_DATUM(new CONST(tf, null, (long) nargs))); 188 cananian 1.1.2.4 else 189 cananian 1.1.2.7 stmlist.add(_DATUM(new CONST(tf, null, (int) nargs))); 190 cananian 1.1.2.2 } 191 cananian 1.1.2.2 private List sortedMembers(HClass hc) { 192 cananian 1.1.2.2 List members = new ArrayList(Arrays.asList(hc.getFields())); 193 cananian 1.1.2.2 members.addAll(Arrays.asList(hc.getMethods())); 194 cananian 1.1.2.9 // add back private members of superclasses, which 195 cananian 1.1.2.9 // getFields()/getMethods() omit. [CSA FIX: 3-28-00] 196 cananian 1.1.2.9 for (HClass hcp=hc.getSuperclass();hcp!=null;hcp=hcp.getSuperclass()) { 197 cananian 1.1.2.9 List l = new ArrayList(Arrays.asList(hcp.getDeclaredFields())); 198 cananian 1.1.2.9 l.addAll(Arrays.asList(hcp.getDeclaredMethods())); 199 cananian 1.6 for (Object hmO : l) { 200 cananian 1.6 HMember hm = (HMember) hmO; 201 cananian 1.1.2.9 if (Modifier.isPrivate(hm.getModifiers())) 202 cananian 1.1.2.9 members.add(hm); 203 cananian 1.1.2.9 } 204 cananian 1.1.2.9 } 205 cananian 1.1.2.10 // add back 'length' field of arrays, which getFields() omits. 206 cananian 1.1.2.10 // [CSA FIX: 11-14-00] 207 cananian 1.1.2.10 if (hc.isArray()) members.add(hc.getDeclaredField("length")); 208 cananian 1.1.2.9 // okay, now sort members. 209 cananian 1.1.2.2 Collections.sort(members, new Comparator() { 210 cananian 1.1.2.2 public int compare(Object o1, Object o2) { 211 cananian 1.1.2.2 HMember hm1 = (HMember) o1, hm2 = (HMember) o2; 212 cananian 1.1.2.2 int r = compareUTF8(hm1.getName(), hm2.getName()); 213 cananian 1.1.2.2 return (r!=0) ? r : 214 cananian 1.1.2.2 compareUTF8(hm1.getDescriptor(), hm2.getDescriptor()); 215 cananian 1.1.2.2 } 216 cananian 1.1.2.2 private int compareUTF8(String s1, String s2) { 217 cananian 1.1.2.2 byte[] b1 = toUTF8(s1), b2 = toUTF8(s2); 218 cananian 1.1.2.2 for (int i=0; i<b1.length && i<b2.length; i++) 219 cananian 1.1.2.2 if (b1[i] != b2[i]) 220 cananian 1.1.2.2 // ack. we want an unsigned comparison 221 cananian 1.1.2.2 return (((int)b1[i])&0xFF) - (((int)b2[i])&0xFF); 222 cananian 1.1.2.2 // okay, they're equal, up to minlen. 223 cananian 1.1.2.2 return b1.length - b2.length; 224 cananian 1.1.2.2 } 225 cananian 1.1.2.2 }); 226 cananian 1.1.2.2 return Collections.unmodifiableList(members); 227 cananian 1.1.2.1 } 228 cananian 1.2 }