Mercurial > hg > graal-compiler
comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java @ 7084:9ba90252ce08
HotSpotResolvedJavaType is now the HotSpot implementation of ResolvedJavaType,
Renamed old HotSpotResolvedJavaType to HotSpotResolvedObjectType
Renamed HotSpotTypePrimitive to HotSpotResolvedPrimitiveType
Renamed HotSpotTypeUnresolved to HotSpotUnresolvedJavaType
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 28 Nov 2012 14:07:25 +0100 |
parents | graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java@fa3c8913d674 |
children | 4c0d132dca4d |
comparison
equal
deleted
inserted
replaced
7083:fa3c8913d674 | 7084:9ba90252ce08 |
---|---|
1 /* | |
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.graal.hotspot.meta; | |
24 | |
25 import static com.oracle.graal.api.meta.MetaUtil.*; | |
26 import static com.oracle.graal.graph.FieldIntrospection.*; | |
27 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; | |
28 import static java.lang.reflect.Modifier.*; | |
29 | |
30 import java.lang.annotation.*; | |
31 import java.lang.reflect.*; | |
32 import java.util.*; | |
33 | |
34 import com.oracle.graal.api.meta.*; | |
35 import com.oracle.graal.hotspot.*; | |
36 | |
37 /** | |
38 * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. | |
39 */ | |
40 public final class HotSpotResolvedObjectType extends HotSpotResolvedJavaType { | |
41 | |
42 private static final long serialVersionUID = 3481514353553840471L; | |
43 | |
44 /** | |
45 * Value for the {@code sizeOrSpecies} parameter in {@link HotSpotResolvedObjectType#HotSpotResolvedObjectType} | |
46 * denoting that the new type represents an interface class. | |
47 */ | |
48 public static final int INTERFACE_SPECIES_VALUE = Integer.MIN_VALUE; | |
49 | |
50 /** | |
51 * Value for the {@code sizeOrSpecies} parameter in {@link HotSpotResolvedObjectType#HotSpotResolvedObjectType} | |
52 * denoting that the new type represents an array class. | |
53 */ | |
54 public static final int ARRAY_SPECIES_VALUE = Integer.MAX_VALUE; | |
55 | |
56 /** | |
57 * Reference to the metaspace Klass object. | |
58 */ | |
59 private final long metaspaceKlass; | |
60 | |
61 private final Class<?> javaMirror; // this could be read directly from 'metaspaceKlass'... | |
62 private final String simpleName; | |
63 private final boolean hasFinalizableSubclass; | |
64 | |
65 /** | |
66 * The instance size for an instance type, {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} denoting | |
67 * an interface type or {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} denoting an array type. | |
68 */ | |
69 private final int sizeOrSpecies; | |
70 | |
71 private HashMap<Long, ResolvedJavaField> fieldCache; | |
72 private HashMap<Long, HotSpotResolvedJavaMethod> methodCache; | |
73 private HotSpotResolvedJavaField[] instanceFields; | |
74 private ResolvedJavaType[] interfaces; | |
75 private ConstantPool constantPool; | |
76 private boolean isInitialized; | |
77 private ResolvedJavaType arrayOfType; | |
78 | |
79 /** | |
80 * Gets the Graal mirror from a HotSpot metaspace Klass native object. | |
81 * | |
82 * @param metaspaceKlass a metaspace Klass object boxed in a {@link Constant} | |
83 * @return the {@link ResolvedJavaType} corresponding to {@code klassConstant} | |
84 */ | |
85 public static ResolvedJavaType fromMetaspaceKlass(Constant metaspaceKlass) { | |
86 assert metaspaceKlass.getKind().isLong(); | |
87 return fromMetaspaceKlass(metaspaceKlass.asLong()); | |
88 } | |
89 | |
90 /** | |
91 * Gets the Graal mirror from a HotSpot metaspace Klass native object. | |
92 * | |
93 * @param metaspaceKlass a metaspace Klass object | |
94 * @return the {@link ResolvedJavaType} corresponding to {@code metaspaceKlass} | |
95 */ | |
96 public static ResolvedJavaType fromMetaspaceKlass(long metaspaceKlass) { | |
97 assert metaspaceKlass != 0; | |
98 Class javaClass = (Class) unsafe.getObject(null, metaspaceKlass + HotSpotGraalRuntime.getInstance().getConfig().classMirrorOffset); | |
99 assert javaClass != null; | |
100 return fromClass(javaClass); | |
101 } | |
102 | |
103 /** | |
104 * Gets the Graal mirror from a {@link Class} object. | |
105 * | |
106 * @return the {@link HotSpotResolvedObjectType} corresponding to {@code javaClass} | |
107 */ | |
108 public static ResolvedJavaType fromClass(Class javaClass) { | |
109 ResolvedJavaType type = (ResolvedJavaType) unsafe.getObject(javaClass, (long) HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset); | |
110 if (type == null) { | |
111 type = HotSpotGraalRuntime.getInstance().getCompilerToVM().getResolvedType(javaClass); | |
112 assert type != null; | |
113 } | |
114 return type; | |
115 } | |
116 | |
117 /** | |
118 * @param hasFinalizableSubclass | |
119 * @param sizeOrSpecies the size of an instance of the type, or {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} | |
120 */ | |
121 public HotSpotResolvedObjectType(long metaspaceKlass, | |
122 String name, | |
123 String simpleName, | |
124 Class javaMirror, | |
125 boolean hasFinalizableSubclass, | |
126 int sizeOrSpecies) { | |
127 super(name); | |
128 this.metaspaceKlass = metaspaceKlass; | |
129 this.javaMirror = javaMirror; | |
130 this.simpleName = simpleName; | |
131 this.hasFinalizableSubclass = hasFinalizableSubclass; | |
132 this.sizeOrSpecies = sizeOrSpecies; | |
133 assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies); | |
134 assert javaMirror.isArray() == isArray(); | |
135 assert javaMirror.isInterface() == isInterface(); | |
136 //System.out.println("0x" + Long.toHexString(metaspaceKlass) + ": " + name); | |
137 } | |
138 | |
139 @Override | |
140 public int getModifiers() { | |
141 return javaMirror.getModifiers(); | |
142 } | |
143 | |
144 public int getAccessFlags() { | |
145 HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); | |
146 return unsafe.getInt(null, metaspaceKlass + config.klassAccessFlagsOffset); | |
147 } | |
148 | |
149 @Override | |
150 public ResolvedJavaType getArrayClass() { | |
151 if (arrayOfType == null) { | |
152 arrayOfType = fromClass(Array.newInstance(javaMirror, 0).getClass()); | |
153 } | |
154 return arrayOfType; | |
155 } | |
156 | |
157 @Override | |
158 public ResolvedJavaType getComponentType() { | |
159 Class javaComponentType = javaMirror.getComponentType(); | |
160 return javaComponentType == null ? null : fromClass(javaComponentType); | |
161 } | |
162 | |
163 private static boolean hasSubtype(ResolvedJavaType type) { | |
164 assert !type.isArray() : type; | |
165 if (type.isPrimitive()) { | |
166 return false; | |
167 } | |
168 HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); | |
169 if (unsafeReadWord(((HotSpotResolvedObjectType) type).metaspaceKlass + config.subklassOffset) != 0) { | |
170 return true; | |
171 } | |
172 return false; | |
173 } | |
174 | |
175 @Override | |
176 public ResolvedJavaType findUniqueConcreteSubtype() { | |
177 HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); | |
178 if (isArray()) { | |
179 if (hasSubtype(getElementalType(this))) { | |
180 return null; | |
181 } | |
182 return this; | |
183 } else { | |
184 HotSpotResolvedObjectType type = this; | |
185 while (isAbstract(type.getModifiers())) { | |
186 long subklass = unsafeReadWord(type.metaspaceKlass + config.subklassOffset); | |
187 if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) { | |
188 return null; | |
189 } | |
190 type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass); | |
191 } | |
192 if (unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) { | |
193 return null; | |
194 } | |
195 return type; | |
196 } | |
197 } | |
198 | |
199 @Override | |
200 public HotSpotResolvedObjectType getSuperclass() { | |
201 Class javaSuperclass = javaMirror.getSuperclass(); | |
202 return javaSuperclass == null ? null : (HotSpotResolvedObjectType) fromClass(javaSuperclass); | |
203 } | |
204 | |
205 @Override | |
206 public ResolvedJavaType[] getInterfaces() { | |
207 if (interfaces == null) { | |
208 Class[] javaInterfaces = javaMirror.getInterfaces(); | |
209 ResolvedJavaType[] result = new ResolvedJavaType[javaInterfaces.length]; | |
210 for (int i = 0; i < javaInterfaces.length; i++) { | |
211 result[i] = fromClass(javaInterfaces[i]); | |
212 } | |
213 interfaces = result; | |
214 } | |
215 return interfaces; | |
216 } | |
217 | |
218 public HotSpotResolvedObjectType getSupertype() { | |
219 if (isArray()) { | |
220 ResolvedJavaType componentType = getComponentType(); | |
221 if (javaMirror == Object[].class || componentType.isPrimitive()) { | |
222 return (HotSpotResolvedObjectType) fromClass(Object.class); | |
223 } | |
224 return (HotSpotResolvedObjectType) ((HotSpotResolvedObjectType) componentType).getSupertype().getArrayClass(); | |
225 } | |
226 if (isInterface()) { | |
227 return (HotSpotResolvedObjectType) fromClass(Object.class); | |
228 } | |
229 return getSuperclass(); | |
230 } | |
231 | |
232 @Override | |
233 public ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType) { | |
234 if (otherType.isPrimitive()) { | |
235 return null; | |
236 } else { | |
237 HotSpotResolvedObjectType t1 = this; | |
238 HotSpotResolvedObjectType t2 = (HotSpotResolvedObjectType) otherType; | |
239 while (true) { | |
240 if (t2.isAssignableTo(t1)) { | |
241 return t1; | |
242 } | |
243 if (t1.isAssignableTo(t2)) { | |
244 return t2; | |
245 } | |
246 t1 = t1.getSupertype(); | |
247 t2 = t2.getSupertype(); | |
248 } | |
249 } | |
250 } | |
251 | |
252 @Override | |
253 public ResolvedJavaType asExactType() { | |
254 if (isArray()) { | |
255 return getComponentType().asExactType() != null ? this : null; | |
256 } | |
257 return Modifier.isFinal(getModifiers()) ? this : null; | |
258 } | |
259 | |
260 @Override | |
261 public Constant getEncoding(Representation r) { | |
262 switch (r) { | |
263 case JavaClass: | |
264 return Constant.forObject(javaMirror); | |
265 case ObjectHub: | |
266 return klass(); | |
267 case StaticPrimitiveFields: | |
268 case StaticObjectFields: | |
269 return Constant.forObject(javaMirror); | |
270 default: | |
271 assert false : "Should not reach here."; | |
272 return null; | |
273 } | |
274 } | |
275 | |
276 @Override | |
277 public boolean hasFinalizableSubclass() { | |
278 return hasFinalizableSubclass; | |
279 } | |
280 | |
281 @Override | |
282 public boolean hasFinalizer() { | |
283 HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); | |
284 return (getAccessFlags() & config.klassHasFinalizerFlag) != 0; | |
285 } | |
286 | |
287 @Override | |
288 public boolean isPrimitive() { | |
289 return false; | |
290 } | |
291 | |
292 @Override | |
293 public boolean isArray() { | |
294 return sizeOrSpecies == ARRAY_SPECIES_VALUE; | |
295 } | |
296 | |
297 @Override | |
298 public boolean isInitialized() { | |
299 if (!isInitialized) { | |
300 isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().isTypeInitialized(this); | |
301 } | |
302 return isInitialized; | |
303 } | |
304 | |
305 @Override | |
306 public void initialize() { | |
307 if (!isInitialized) { | |
308 HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeType(this); | |
309 } | |
310 isInitialized = true; | |
311 } | |
312 | |
313 @Override | |
314 public boolean isInstance(Constant obj) { | |
315 if (obj.getKind().isObject() && !obj.isNull()) { | |
316 return javaMirror.isInstance(obj.asObject()); | |
317 } | |
318 return false; | |
319 } | |
320 | |
321 @Override | |
322 public boolean isInstanceClass() { | |
323 return !isArray() && !isInterface(); | |
324 } | |
325 | |
326 @Override | |
327 public boolean isInterface() { | |
328 return sizeOrSpecies == INTERFACE_SPECIES_VALUE; | |
329 } | |
330 | |
331 @Override | |
332 public boolean isAssignableTo(ResolvedJavaType other) { | |
333 if (other instanceof HotSpotResolvedObjectType) { | |
334 HotSpotResolvedObjectType otherType = (HotSpotResolvedObjectType) other; | |
335 return otherType.javaMirror.isAssignableFrom(javaMirror); | |
336 } | |
337 return false; | |
338 } | |
339 | |
340 @Override | |
341 public Kind getKind() { | |
342 return Kind.Object; | |
343 } | |
344 | |
345 @Override | |
346 public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { | |
347 assert method instanceof HotSpotMethod; | |
348 return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).asString()); | |
349 } | |
350 | |
351 @Override | |
352 public String toString() { | |
353 return "HotSpotType<" + simpleName + ", resolved>"; | |
354 } | |
355 | |
356 public ConstantPool constantPool() { | |
357 if (constantPool == null) { | |
358 constantPool = new HotSpotConstantPool(this); | |
359 } | |
360 return constantPool; | |
361 } | |
362 | |
363 /** | |
364 * Gets the instance size of this type. If an instance of this type cannot | |
365 * be fast path allocated, then the returned value is negative (its absolute | |
366 * value gives the size). Must not be called if this is an array or interface type. | |
367 */ | |
368 public int instanceSize() { | |
369 assert !isArray(); | |
370 assert !isInterface(); | |
371 return sizeOrSpecies; | |
372 } | |
373 | |
374 public synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) { | |
375 HotSpotResolvedJavaMethod method = null; | |
376 if (methodCache == null) { | |
377 methodCache = new HashMap<>(8); | |
378 } else { | |
379 method = methodCache.get(metaspaceMethod); | |
380 } | |
381 if (method == null) { | |
382 method = new HotSpotResolvedJavaMethod(this, metaspaceMethod); | |
383 methodCache.put(metaspaceMethod, method); | |
384 } | |
385 return method; | |
386 } | |
387 | |
388 public synchronized ResolvedJavaField createField(String fieldName, JavaType type, int offset, int flags, boolean internal) { | |
389 ResolvedJavaField result = null; | |
390 | |
391 long id = offset + ((long) flags << 32); | |
392 | |
393 // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical. | |
394 if (fieldCache == null) { | |
395 fieldCache = new HashMap<>(8); | |
396 } else { | |
397 result = fieldCache.get(id); | |
398 } | |
399 | |
400 if (result == null) { | |
401 result = new HotSpotResolvedJavaField(this, fieldName, type, offset, flags, internal); | |
402 fieldCache.put(id, result); | |
403 } else { | |
404 assert result.getName().equals(fieldName); | |
405 assert result.getModifiers() == (Modifier.fieldModifiers() & flags); | |
406 } | |
407 | |
408 return result; | |
409 } | |
410 | |
411 @Override | |
412 public ResolvedJavaMethod findUniqueConcreteMethod(ResolvedJavaMethod method) { | |
413 return ((HotSpotResolvedJavaMethod) method).uniqueConcreteMethod(); | |
414 } | |
415 | |
416 @Override | |
417 public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { | |
418 if (instanceFields == null) { | |
419 if (isArray() || isInterface()) { | |
420 instanceFields = new HotSpotResolvedJavaField[0]; | |
421 } else { | |
422 HotSpotResolvedJavaField[] myFields = HotSpotGraalRuntime.getInstance().getCompilerToVM().getInstanceFields(this); | |
423 if (javaMirror != Object.class) { | |
424 HotSpotResolvedJavaField[] superFields = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); | |
425 HotSpotResolvedJavaField[] fields = Arrays.copyOf(superFields, superFields.length + myFields.length); | |
426 System.arraycopy(myFields, 0, fields, superFields.length, myFields.length); | |
427 instanceFields = fields; | |
428 } else { | |
429 assert myFields.length == 0 : "java.lang.Object has fields!"; | |
430 instanceFields = myFields; | |
431 } | |
432 } | |
433 } | |
434 if (!includeSuperclasses) { | |
435 int myFieldsStart = 0; | |
436 while (myFieldsStart < instanceFields.length && instanceFields[myFieldsStart].getDeclaringClass() != this) { | |
437 myFieldsStart++; | |
438 } | |
439 if (myFieldsStart == 0) { | |
440 return instanceFields; | |
441 } | |
442 if (myFieldsStart == instanceFields.length) { | |
443 return new HotSpotResolvedJavaField[0]; | |
444 } | |
445 return Arrays.copyOfRange(instanceFields, myFieldsStart, instanceFields.length); | |
446 } | |
447 return instanceFields; | |
448 } | |
449 | |
450 @Override | |
451 public Class<?> mirror() { | |
452 return javaMirror; | |
453 } | |
454 | |
455 @Override | |
456 public boolean isClass(Class c) { | |
457 return c == javaMirror; | |
458 } | |
459 | |
460 @Override | |
461 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { | |
462 return javaMirror.getAnnotation(annotationClass); | |
463 } | |
464 | |
465 @Override | |
466 public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { | |
467 return this; | |
468 } | |
469 | |
470 /** | |
471 * Gets the address of the C++ Klass object for this type. | |
472 */ | |
473 public Constant klass() { | |
474 return new Constant(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceKlass, this); | |
475 } | |
476 | |
477 public boolean isPrimaryType() { | |
478 return HotSpotGraalRuntime.getInstance().getConfig().secondarySuperCacheOffset != superCheckOffset(); | |
479 } | |
480 | |
481 public int superCheckOffset() { | |
482 HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); | |
483 return unsafe.getInt(null, metaspaceKlass + config.superCheckOffsetOffset); | |
484 } | |
485 | |
486 public long prototypeMarkWord() { | |
487 return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); | |
488 } | |
489 | |
490 @Override | |
491 public ResolvedJavaField findInstanceFieldWithOffset(long offset) { | |
492 ResolvedJavaField[] declaredFields = getInstanceFields(true); | |
493 for (ResolvedJavaField field : declaredFields) { | |
494 if (((HotSpotResolvedJavaField) field).offset() == offset) { | |
495 return field; | |
496 } | |
497 } | |
498 return null; | |
499 } | |
500 } |