1 cananian 1.1.2.1 // DataReflection1.java, created Sat Oct 16 13:43:17 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.Generic.Runtime.ObjectBuilder.ObjectInfo;
  9 cananian 1.1.2.1 import harpoon.Backend.Generic.Runtime.ObjectBuilder;
 10 cananian 1.1.2.1 import harpoon.Backend.Maps.NameMap;
 11 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
 12 cananian 1.1.2.1 import harpoon.ClassFile.HDataElement;
 13 cananian 1.1.2.1 import harpoon.ClassFile.HField;
 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.2 import harpoon.IR.Tree.ALIGN;
 18 cananian 1.1.2.1 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.1 import java.util.ArrayList;
 24 cananian 1.1.2.1 import java.util.Collections;
 25 cananian 1.1.2.1 import java.util.Comparator;
 26 cananian 1.1.2.1 import java.util.Iterator;
 27 cananian 1.1.2.1 import java.util.List;
 28 cananian 1.1.2.1 /**
 29 cananian 1.1.2.1  * <code>DataReflection1</code> creates tables which the JNI interface
 30 cananian 1.1.2.1  * will use.  This includes:<OL>
 31 cananian 1.1.2.1  * <LI>a table to map class names to <code>java.lang.Class</code> objects,
 32 cananian 1.1.2.1  *     sorted in order of the UTF-8 encodings of the class names.
 33 cananian 1.1.2.6  *     (begins at <code>name2class_start</code>, ends at
 34 cananian 1.1.2.6  *      <code>name2class_end</code>)
 35 cananian 1.1.2.1  * <LI>a table to map <code>java.lang.Class</code> objects to class
 36 cananian 1.1.2.1  *     information structures, sorted in order of the (non-relocatable)
 37 cananian 1.1.2.1  *     <code>Class</code> object address.
 38 cananian 1.1.2.6  *     (begins at <code>class2info_start</code>, ends at
 39 cananian 1.1.2.6  *      <code>class2info_end</code>)
 40 cananian 1.1.2.1  * <LI>UTF-8 encoded class name strings, used by the first table as
 41 cananian 1.1.2.1  *     well as by the class information structures.
 42 cananian 1.1.2.1  * <LI>Static <Code>java.lang.Class</code> objects.  As the JDK dictates,
 43 cananian 1.1.2.1  *     these contain no actual class data; however, table #2 above can
 44 cananian 1.1.2.1  *     be keyed by the object address to fetch the actual class information
 45 cananian 1.1.2.1  *     structures.
 46 cananian 1.1.2.1  * </OL>
 47 cananian 1.1.2.1  * 
 48 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 49 cananian 1.6      * @version $Id: DataReflection1.java,v 1.6 2004/02/08 03:20:58 cananian Exp $
 50 cananian 1.1.2.1  */
 51 cananian 1.1.2.1 public class DataReflection1 extends Data {
 52 cananian 1.1.2.1     final NameMap m_nm;
 53 cananian 1.1.2.1     final ObjectBuilder m_ob;
 54 cananian 1.1.2.1     
 55 cananian 1.1.2.1     /** Creates a <code>DataReflection1</code>. */
 56 cananian 1.1.2.1     public DataReflection1(Frame f, HClass hc, ClassHierarchy ch) {
 57 cananian 1.1.2.1         super("reflection-data-1", hc, f);
 58 cananian 1.1.2.9         this.m_nm = f.getRuntime().getNameMap();
 59 cananian 1.1.2.1         this.m_ob = ((Runtime) f.getRuntime()).ob;
 60 cananian 1.1.2.1         // only build one of these (so we can make sure the
 61 cananian 1.1.2.1         // table is properly sorted); wait until hc is
 62 cananian 1.1.2.1         // java.lang.Object
 63 cananian 1.1.2.5         this.root = (hc==linker.forName("java.lang.Object")) ?
 64 cananian 1.1.2.1             build(ch) : null;
 65 cananian 1.1.2.1     }
 66 cananian 1.1.2.1     private HDataElement build(ClassHierarchy ch) {
 67 cananian 1.1.2.1         // okay, some preliminaries first: build properly sorted list of
 68 cananian 1.1.2.1         // classes.
 69 cananian 1.1.2.1         List sorted = new ArrayList(ch.classes());
 70 cananian 1.1.2.1         Collections.sort(sorted, new Comparator() {
 71 cananian 1.1.2.1             public int compare(Object o1, Object o2) {
 72 cananian 1.1.2.1                 // compare two classes by ordering the UTF-8 encodings of
 73 cananian 1.1.2.1                 // their names.
 74 cananian 1.1.2.1                 byte[] b1 = toUTF8(((HClass)o1).getName().replace('.','/'));
 75 cananian 1.1.2.1                 byte[] b2 = toUTF8(((HClass)o2).getName().replace('.','/'));
 76 cananian 1.1.2.1                 for (int i=0; i<b1.length && i<b2.length; i++)
 77 cananian 1.1.2.1                     if (b1[i] != b2[i])
 78 cananian 1.1.2.1                         // ack.  we want an unsigned comparison
 79 cananian 1.1.2.1                         return (((int)b1[i])&0xFF) - (((int)b2[i])&0xFF);
 80 cananian 1.1.2.1                 // okay, they're equal, up to minlen.
 81 cananian 1.1.2.1                 return b1.length - b2.length;
 82 cananian 1.1.2.1             }
 83 cananian 1.1.2.1         });
 84 cananian 1.1.2.1         // yay, team.  we've got a properly sorted list.
 85 cananian 1.1.2.1 
 86 cananian 1.1.2.1         List stmlist = new ArrayList(6);
 87 cananian 1.1.2.1         // change to table data segment.
 88 cananian 1.1.2.1         stmlist.add(new SEGMENT(tf, null, SEGMENT.REFLECTION_DATA));
 89 cananian 1.1.2.1         // build class name string -> class object table.
 90 cananian 1.1.2.1         stmlist.add(buildStr2Class(sorted));
 91 cananian 1.1.2.1         // build class object -> class info table.
 92 cananian 1.1.2.1         stmlist.add(buildClass2Info(sorted));
 93 cananian 1.1.2.1         // build class name strings
 94 cananian 1.1.2.1         stmlist.add(buildStrings(sorted));
 95 cananian 1.1.2.1         // change to object data segment.
 96 cananian 1.1.2.1         stmlist.add(new SEGMENT(tf, null, SEGMENT.REFLECTION_OBJECTS));
 97 cananian 1.1.2.1         // build actual class objects
 98 cananian 1.1.2.1         stmlist.add(buildClassObjects(sorted));
 99 cananian 1.1.2.1         // yay, done.
100 cananian 1.1.2.1         return (HDataElement) Stm.toStm(stmlist);
101 cananian 1.1.2.1     }
102 cananian 1.1.2.1     private Stm buildStr2Class(List sorted) {
103 cananian 1.4             Label ls, le;
104 cananian 1.1.2.2         List stmlist = new ArrayList(3+2*sorted.size());
105 cananian 1.1.2.1         // make a sorted table mapping name strings to class objects.
106 cananian 1.4             stmlist.add(new ALIGN(tf, null, 8)); // align table to double-word boundary
107 cananian 1.1.2.1         stmlist.add(new LABEL(tf, null,
108 cananian 1.4                                   ls = new Label(m_nm.c_function_name
109 cananian 1.4                                                  ("name2class_start")), true));
110 cananian 1.6             for (Object hcO : sorted) {
111 cananian 1.6                 HClass hc = (HClass) hcO;
112 cananian 1.1.2.4             stmlist.add(_DATUM(m_nm.label(hc, "namestr")));
113 cananian 1.1.2.4             stmlist.add(_DATUM(m_nm.label(hc, "classobj")));
114 cananian 1.1.2.1         }
115 cananian 1.1.2.1         stmlist.add(new LABEL(tf, null,
116 cananian 1.4                                   le = new Label(m_nm.c_function_name
117 cananian 1.4                                                  ("name2class_end")), true));
118 cananian 1.4             // add two bogus words to keep gcc from putting class2info_end into
119 cananian 1.4             // the BSS segment when compiling with PreciseC and NO_SECTION_SUPPORT
120 cananian 1.4             stmlist.add(_DATUM(ls));
121 cananian 1.4             stmlist.add(_DATUM(le));
122 cananian 1.4             // okay, done now.
123 cananian 1.1.2.1         return Stm.toStm(stmlist);
124 cananian 1.1.2.1     }
125 cananian 1.1.2.1     private Stm buildClass2Info(List sorted) {
126 cananian 1.4             Label ls, le;
127 cananian 1.1.2.2         List stmlist = new ArrayList(3+2*sorted.size());
128 cananian 1.1.2.1         // make a sorted table mapping class objects to class info structures.
129 cananian 1.5             stmlist.add(new ALIGN(tf, null, 8)); // align table to double-word boundary
130 cananian 1.1.2.1         stmlist.add(new LABEL(tf, null,
131 cananian 1.4                                   ls = new Label(m_nm.c_function_name
132 cananian 1.4                                                  ("class2info_start")), true));
133 cananian 1.6             for (Object hcO : sorted) {
134 cananian 1.6                 HClass hc = (HClass) hcO;
135 cananian 1.1.2.4             stmlist.add(_DATUM(m_nm.label(hc, "classobj")));
136 cananian 1.1.2.4             stmlist.add(_DATUM(m_nm.label(hc, "classinfo")));
137 cananian 1.1.2.1         }
138 cananian 1.1.2.1         stmlist.add(new LABEL(tf, null,
139 cananian 1.4                                   le = new Label(m_nm.c_function_name
140 cananian 1.4                                                  ("class2info_end")), true));
141 cananian 1.4             // add two bogus words to keep gcc from putting class2info_end into
142 cananian 1.4             // the BSS segment when compiling with PreciseC and NO_SECTION_SUPPORT
143 cananian 1.4             stmlist.add(_DATUM(ls));
144 cananian 1.4             stmlist.add(_DATUM(le));
145 cananian 1.4             // okay, done now.
146 cananian 1.1.2.1         return Stm.toStm(stmlist);
147 cananian 1.1.2.1     }
148 cananian 1.1.2.1     private Stm buildStrings(List sorted) {
149 cananian 1.1.2.3         List stmlist = new ArrayList(1+2*sorted.size());
150 cananian 1.1.2.1         // build actual c-style string data from UTF-8 encoded class name
151 cananian 1.6             for (Object hcO : sorted) {
152 cananian 1.6                 HClass hc = (HClass) hcO;
153 cananian 1.1.2.1             stmlist.add(new LABEL(tf, null, m_nm.label(hc, "namestr"), true));
154 cananian 1.1.2.3             stmlist.add(emitUtf8String(hc.getName().replace('.','/')));
155 cananian 1.1.2.1         }
156 cananian 1.1.2.2         // pad out to a full word after the last byte.
157 cananian 1.1.2.2         stmlist.add(new ALIGN(tf, null, 4));
158 cananian 1.1.2.1         return Stm.toStm(stmlist);
159 cananian 1.1.2.1     }
160 cananian 1.1.2.1     private Stm buildClassObjects(List sorted) {
161 cananian 1.1.2.1         List stmlist = new ArrayList(sorted.size());
162 cananian 1.1.2.5         final HClass HCclass = linker.forName("java.lang.Class");
163 cananian 1.1.2.1         for (Iterator it=sorted.iterator(); it.hasNext(); ) {
164 cananian 1.1.2.1             final HClass hc = (HClass) it.next();
165 cananian 1.1.2.1             // make an ObjectInfo -- that doesn't actual provide any info.
166 cananian 1.1.2.1             ObjectInfo info = new ObjectInfo() {
167 cananian 1.1.2.1                 public HClass type() { return HCclass; }
168 cananian 1.1.2.1                 public Label label() { return m_nm.label(hc, "classobj"); }
169 cananian 1.1.2.1                 public Object get(HField hf) {
170 cananian 1.3                         if (hf.getDeclaringClass().equals(HCclass) &&
171 cananian 1.3                             (hf.getName().equals("signers") ||
172 cananian 1.3                              hf.getName().equals("pd")))
173 cananian 1.3                             return null;
174 cananian 1.3                         throw new Error("Unknown field of Class object: "+hf);
175 cananian 1.1.2.1                 }
176 cananian 1.1.2.1             };
177 cananian 1.1.2.1             stmlist.add(m_ob.buildObject(tf, info, true));
178 cananian 1.1.2.1         }
179 cananian 1.1.2.1         return Stm.toStm(stmlist);
180 cananian 1.1.2.1     }
181 cananian 1.2     }