1
2
3
4 package joeq.Class;
5
6 import java.util.StringTokenizer;
7 import java.io.IOException;
8 import joeq.ClassLib.ClassLibInterface;
9 import joeq.Main.jq;
10 import joeq.Runtime.Debug;
11 import joeq.Runtime.Reflection;
12 import joeq.UTF.Utf8;
13 import jwutil.io.Textualizable;
14 import jwutil.io.Textualizer;
15 import jwutil.util.Assert;
16
17
18
19
20
21 public abstract class jq_Type implements Textualizable {
22
23 protected final Utf8 desc;
24 private
25
26 public static final boolean USE_CLASS_OBJECT_FIELD = true;
27
28 protected jq_Type(Utf8 desc, ClassLoader class_loader) {
29 this.desc = desc;
30 initializeClassObject();
31 }
32
33 private void initializeClassObject() {
34 if (jq.RunningNative)
35 this.class_object = ClassLibInterface.DEFAULT.createNewClass(this);
36 else if (USE_CLASS_OBJECT_FIELD)
37 this.class_object = Reflection.getJDKType(this);
38 }
39
40 public abstract String getName();
41 public abstract String shortName();
42 public final Utf8 getDesc() { return desc; }
43 public abstract String getJDKDesc();
44 public abstract boolean isClassType();
45 public abstract boolean isArrayType();
46 public abstract boolean isPrimitiveType();
47 public abstract boolean isAddressType();
48 public abstract boolean isIntLike();
49 public final boolean isReferenceType() { return !isPrimitiveType(); }
50 public abstract ClassLoader getClassLoader();
51 public abstract int getReferenceSize();
52 public final jq_Array getArrayTypeForElementType() {
53 return (jq_Array)PrimordialClassLoader.getOrCreateType(getClassLoader(), desc.getAsArrayDescriptor());
54 }
55 public boolean needsDynamicLink(jq_Method method) { return false; }
56 public abstract boolean isInstance(Object o);
57 public abstract int getDepth();
58 public final Class getJavaLangClassObject() {
59 if (jq.RunningNative && this.class_object == null)
60 initializeClassObject();
61 return class_object;
62 }
63
64 public static final int DISPLAY_SIZE = 8;
65
66 /***
67 * The first two elements are the positive and negative cache,
68 * respectively. The remainder are the primary supertypes of this type
69 * ordered by the tree relation. This array should be inlined into the
70 * jq_Type object, hopefully.
71 *
72 * See paper "Fast subtype checking in the HotSpot JVM".
73 */
74 protected jq_Type[] display;
75
76 /***
77 * The offset of our type in the display array if this is a primary type, or
78 * 0 or 1 if this is a secondary type.
79 *
80 * See paper "Fast subtype checking in the HotSpot JVM".
81 */
82 protected int offset;
83
84 /***
85 * A reference to the secondary subtype array for this type.
86 *
87 * See paper "Fast subtype checking in the HotSpot JVM".
88 */
89 protected jq_Reference[] s_s_array;
90
91 /***
92 * The maximum index used in the secondary subtype array.
93 *
94 * See paper "Fast subtype checking in the HotSpot JVM".
95 */
96 protected int s_s_array_length;
97
98
99
100 public static String convertPrimitive(String s) {
101 if (s.equals("byte")) return "B";
102 if (s.equals("char")) return "C";
103 if (s.equals("double")) return "D";
104 if (s.equals("float")) return "F";
105 if (s.equals("int")) return "I";
106 if (s.equals("long")) return "J";
107 if (s.equals("short")) return "S";
108 if (s.equals("void")) return "V";
109 if (s.equals("boolean")) return "Z";
110 return s;
111 }
112
113 public static jq_Type parseType(String s) {
114 s = convertPrimitive (s);
115 if (s.length() == 1) {
116 jq_Primitive t = (jq_Primitive) PrimordialClassLoader.loader.getBSType(s);
117 if (t != null) return t;
118 s = "L" + s + ";";
119 } else {
120 s = s.replace('.', '/');
121 int arrayDepth = 0;
122 while (s.endsWith("[]")) {
123 ++arrayDepth;
124 s = s.substring(0, s.length() - 2);
125 }
126 s = convertPrimitive (s);
127 if (s.length() == 1) {
128 jq_Primitive t = (jq_Primitive) PrimordialClassLoader.loader.getBSType(s);
129 if (t == null)
130 s = "L" + s + ";";
131 } else if (!s.startsWith("[") && !s.endsWith(";"))
132 s = "L" + s + ";";
133 while (--arrayDepth >= 0)
134 s = "[" + s;
135 }
136 return (jq_Reference) PrimordialClassLoader.loader.getOrCreateBSType(s);
137 }
138
139 public static final boolean TRACE = false;
140
141 public final boolean isSubtypeOf(jq_Type that) {
142 Assert._assert(this.isPrepared());
143 Assert._assert(that.isPrepared());
144
145 int off = that.offset;
146 if (that == this.display[off]) {
147
148 if (TRACE) {
149 Debug.write(this.getDesc());
150 Debug.write(" matches ");
151 Debug.write(that.getDesc());
152 Debug.write(" offset=");
153 Debug.writeln(off);
154 }
155 return off != 1;
156 }
157 if (this == jq_Reference.jq_NullType.NULL_TYPE) {
158 return that.isReferenceType();
159 }
160 if (off > 1) {
161
162 if (TRACE) {
163 Debug.write(this.getDesc());
164 Debug.write(" doesn't match ");
165 Debug.write(that.getDesc());
166 Debug.write(", offset ");
167 Debug.write(off);
168 Debug.write(" is ");
169 if (this.display[off] == null)
170 Debug.writeln("null");
171 else
172 Debug.writeln(this.display[off].getDesc());
173 }
174 return false;
175 }
176 if (this == that) {
177
178 return true;
179 }
180 int n = this.s_s_array_length;
181 for (int i=0; i<n; ++i) {
182 if (this.s_s_array[i] == that) {
183 this.display[0] = that;
184 that.offset = 0;
185 if (TRACE) {
186 Debug.write(this.getDesc());
187 Debug.write(" matches ");
188 Debug.write(that.getDesc());
189 Debug.writeln(" in s_s_array");
190 }
191 return true;
192 }
193 }
194 this.display[1] = that;
195 that.offset = 1;
196 if (TRACE) {
197 Debug.write(this.getDesc());
198 Debug.write(" doesn't match ");
199 Debug.write(that.getDesc());
200 Debug.writeln(" in s_s_array");
201 }
202 return false;
203 }
204
205
206
207
208
209
210
211 public abstract boolean isLoaded();
212 public abstract boolean isVerified();
213 public abstract boolean isPrepared();
214 public abstract boolean isSFInitialized();
215 public abstract boolean isCompiled();
216 public abstract boolean isClsInitRunning();
217 public abstract boolean isClsInitialized();
218
219 public abstract boolean isFinal();
220
221 public abstract void load();
222 public abstract void verify();
223 public abstract void prepare();
224 public abstract void sf_initialize();
225 public abstract void compile();
226 public abstract void cls_initialize();
227
228 public void accept(jq_TypeVisitor tv) { tv.visitType(this); }
229
230 public String toString() { return getName(); }
231
232 public void write(Textualizer t) throws IOException {
233 t.writeString(getDesc().toString());
234 }
235 public void writeEdges(Textualizer t) throws IOException { }
236 public void addEdge(String edgeName, Textualizable t) { }
237 public static jq_Type read(StringTokenizer st) {
238 String desc = st.nextToken();
239 if (desc.equals("null")) return null;
240 jq_Type r = PrimordialClassLoader.loader.getOrCreateBSType(desc);
241 return r;
242 }
243 public static final jq_Class _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Class/jq_Type;");
244 }