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 }