001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.classloader;
014
015 import org.jikesrvm.VM;
016 import static org.jikesrvm.SizeConstants.BYTES_IN_ADDRESS;
017
018 import org.jikesrvm.runtime.ReflectionBase;
019 import org.jikesrvm.util.ImmutableEntryHashSetRVM;
020
021 // TODO: The following is due to a bug in checkstyle 4.3
022 // CHECKSTYLE:OFF
023 import org.vmmagic.pragma.Uninterruptible;
024 // CHECKSTYLE:ON
025
026 /**
027 * A class to represent the reference in a class file to some
028 * type (class, primitive or array).
029 * A type reference is uniquely defined by
030 * <ul>
031 * <li> an initiating class loader
032 * <li> a type name
033 * </ul>
034 * Resolving a TypeReference to a RVMType can
035 * be an expensive operation. Therefore we canonicalize
036 * TypeReference instances and cache the result of resolution.
037 */
038 public final class TypeReference {
039 /**
040 * The initiating class loader
041 */
042 final ClassLoader classloader;
043
044 /**
045 * The type name. For example, the primitive type int is "I", the
046 * class java.lang.String is "Ljava/lang/String;"
047 */
048 final Atom name;
049
050 /**
051 * The id of this type reference.
052 */
053 final int id;
054
055 /**
056 * The RVMType instance that this type reference resolves to.
057 * Null if the reference has not yet been resolved.
058 */
059 private RVMType type;
060
061 /**
062 * Used to canonicalize TypeReferences
063 */
064 private static final ImmutableEntryHashSetRVM<TypeReference> dictionary =
065 new ImmutableEntryHashSetRVM<TypeReference>();
066
067 /**
068 * 2^LOG_ROW_SIZE is the number of elements per row
069 */
070 private static final int LOG_ROW_SIZE = 10;
071 /**
072 * Mask to ascertain row from id number
073 */
074 private static final int ROW_MASK = (1 << LOG_ROW_SIZE)-1;
075 /**
076 * Dictionary of all TypeReference instances.
077 */
078 private static TypeReference[][] types = new TypeReference[3][1<<LOG_ROW_SIZE];
079
080 /**
081 * Used to assign Ids. Id 0 is not used. Ids are compressed and
082 * stored in the constant pool (See {@link RVMClass}).
083 */
084 private static int nextId = 1;
085
086 public static final TypeReference Void = findOrCreate("V");
087 public static final TypeReference Boolean = findOrCreate("Z");
088 public static final TypeReference Byte = findOrCreate("B");
089 public static final TypeReference Char = findOrCreate("C");
090 public static final TypeReference Short = findOrCreate("S");
091 public static final TypeReference Int = findOrCreate("I");
092 public static final TypeReference Long = findOrCreate("J");
093 public static final TypeReference Float = findOrCreate("F");
094 public static final TypeReference Double = findOrCreate("D");
095
096 public static final TypeReference BooleanArray = findOrCreate("[Z");
097 public static final TypeReference ByteArray = findOrCreate("[B");
098 public static final TypeReference CharArray = findOrCreate("[C");
099 public static final TypeReference ShortArray = findOrCreate("[S");
100 public static final TypeReference IntArray = findOrCreate("[I");
101 public static final TypeReference LongArray = findOrCreate("[J");
102 public static final TypeReference FloatArray = findOrCreate("[F");
103 public static final TypeReference DoubleArray = findOrCreate("[D");
104
105 public static final TypeReference Word = findOrCreate(org.vmmagic.unboxed.Word.class);
106 public static final TypeReference Address = findOrCreate(org.vmmagic.unboxed.Address.class);
107 public static final TypeReference ObjectReference = findOrCreate(org.vmmagic.unboxed.ObjectReference.class);
108 public static final TypeReference Offset = findOrCreate(org.vmmagic.unboxed.Offset.class);
109 public static final TypeReference Extent = findOrCreate(org.vmmagic.unboxed.Extent.class);
110 public static final TypeReference Code =
111 findOrCreate(VM.BuildForIA32 ? "Lorg/jikesrvm/ia32/Code;" : "Lorg/jikesrvm/ppc/Code;");
112 public static final TypeReference WordArray = findOrCreate(org.vmmagic.unboxed.WordArray.class);
113 public static final TypeReference AddressArray = findOrCreate(org.vmmagic.unboxed.AddressArray.class);
114 public static final TypeReference ObjectReferenceArray =
115 findOrCreate(org.vmmagic.unboxed.ObjectReferenceArray.class);
116 public static final TypeReference OffsetArray = findOrCreate(org.vmmagic.unboxed.OffsetArray.class);
117 public static final TypeReference ExtentArray = findOrCreate(org.vmmagic.unboxed.ExtentArray.class);
118 public static final TypeReference CodeArray = findOrCreate(org.jikesrvm.ArchitectureSpecific.CodeArray.class);
119 public static final TypeReference Magic = findOrCreate(org.jikesrvm.runtime.Magic.class);
120 public static final TypeReference SysCall = findOrCreate(org.vmmagic.pragma.SysCallNative.class);
121 public static final TypeReference TIB = findOrCreate(org.jikesrvm.objectmodel.TIB.class);
122 public static final TypeReference ITableArray = findOrCreate(org.jikesrvm.objectmodel.ITableArray.class);
123 public static final TypeReference ITable = findOrCreate(org.jikesrvm.objectmodel.ITable.class);
124 public static final TypeReference IMT = findOrCreate(org.jikesrvm.objectmodel.IMT.class);
125 public static final TypeReference Thread = findOrCreate(org.jikesrvm.scheduler.RVMThread.class);
126 public static final TypeReference FunctionTable = findOrCreate(org.jikesrvm.jni.FunctionTable.class);
127 public static final TypeReference LinkageTripletTable = findOrCreate(org.jikesrvm.jni.LinkageTripletTable.class);
128
129 public static final TypeReference JavaLangObject = findOrCreate(java.lang.Object.class);
130 public static final TypeReference JavaLangClass = findOrCreate(java.lang.Class.class);
131 public static final TypeReference JavaLangString = findOrCreate(java.lang.String.class);
132 public static final TypeReference JavaLangCloneable = findOrCreate(java.lang.Cloneable.class);
133 public static final TypeReference JavaIoSerializable = findOrCreate(java.io.Serializable.class);
134 public static final TypeReference JavaLangRefReference = findOrCreate(java.lang.ref.Reference.class);
135 public static final TypeReference JavaLangSystem = findOrCreate(java.lang.System.class);
136
137 public static final TypeReference JavaLangObjectArray = findOrCreate(java.lang.Object[].class);
138
139 public static final TypeReference JavaLangThrowable = findOrCreate(java.lang.Throwable.class);
140 public static final TypeReference JavaLangError = findOrCreate(java.lang.Error.class);
141 public static final TypeReference JavaLangNullPointerException =
142 findOrCreate(java.lang.NullPointerException.class);
143 public static final TypeReference JavaLangArrayIndexOutOfBoundsException =
144 findOrCreate(java.lang.ArrayIndexOutOfBoundsException.class);
145 public static final TypeReference JavaLangArithmeticException = findOrCreate(java.lang.ArithmeticException.class);
146 public static final TypeReference JavaLangArrayStoreException = findOrCreate(java.lang.ArrayStoreException.class);
147 public static final TypeReference JavaLangClassCastException = findOrCreate(java.lang.ClassCastException.class);
148 public static final TypeReference JavaLangNegativeArraySizeException =
149 findOrCreate(java.lang.NegativeArraySizeException.class);
150 public static final TypeReference JavaLangIllegalMonitorStateException =
151 findOrCreate(java.lang.IllegalMonitorStateException.class);
152
153 public static final TypeReference Type = findOrCreate(org.jikesrvm.classloader.RVMType.class);
154 public static final TypeReference Class = findOrCreate(org.jikesrvm.classloader.RVMClass.class);
155
156 public static final TypeReference NativeBridge = findOrCreate(org.vmmagic.pragma.NativeBridge.class);
157 public static final TypeReference DynamicBridge = findOrCreate(org.vmmagic.pragma.DynamicBridge.class);
158 public static final TypeReference SaveVolatile = findOrCreate(org.vmmagic.pragma.SaveVolatile.class);
159 public static final TypeReference Interruptible = findOrCreate(org.vmmagic.pragma.Interruptible.class);
160 public static final TypeReference LogicallyUninterruptible =
161 findOrCreate(org.vmmagic.pragma.LogicallyUninterruptible.class);
162 public static final TypeReference Preemptible = findOrCreate(org.vmmagic.pragma.Preemptible.class);
163 public static final TypeReference UninterruptibleNoWarn =
164 findOrCreate(org.vmmagic.pragma.UninterruptibleNoWarn.class);
165 public static final TypeReference UnpreemptibleNoWarn =
166 findOrCreate(org.vmmagic.pragma.UnpreemptibleNoWarn.class);
167 public static final TypeReference Uninterruptible = findOrCreate(org.vmmagic.pragma.Uninterruptible.class);
168 public static final TypeReference NoCheckStore = findOrCreate(org.vmmagic.pragma.NoCheckStore.class);
169 public static final TypeReference Unpreemptible = findOrCreate(org.vmmagic.pragma.Unpreemptible.class);
170 public static final TypeReference SpecializedMethodInvoke = findOrCreate(org.vmmagic.pragma.SpecializedMethodInvoke.class);
171 public static final TypeReference Untraced = findOrCreate(org.vmmagic.pragma.Untraced.class);
172 public static final TypeReference NonMoving = findOrCreate(org.vmmagic.pragma.NonMoving.class);
173 public static final TypeReference NonMovingAllocation = findOrCreate(org.vmmagic.pragma.NonMovingAllocation.class);
174 public static final TypeReference BaselineNoRegisters = findOrCreate(org.vmmagic.pragma.BaselineNoRegisters.class);
175 public static final TypeReference BaselineSaveLSRegisters = findOrCreate(org.vmmagic.pragma.BaselineSaveLSRegisters.class);
176
177
178 public static final TypeReference ReferenceMaps =
179 findOrCreate(org.jikesrvm.compilers.baseline.ReferenceMaps.class);
180 public static final TypeReference JNIFunctions = findOrCreate(org.jikesrvm.jni.JNIFunctions.class);
181
182 public static final TypeReference CollectorThread =
183 findOrCreate(org.jikesrvm.mm.mminterface.CollectorThread.class);
184
185 public static final TypeReference RVMArray = findOrCreate(org.jikesrvm.classloader.RVMArray.class);
186 /** Abstract base of reflective method invoker classes */
187 static final TypeReference baseReflectionClass = TypeReference.findOrCreate(ReflectionBase.class);
188
189 // Synthetic types used by the opt compiler
190 public static final TypeReference NULL_TYPE =
191 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$NULL;") : null;
192 public static final TypeReference VALIDATION_TYPE =
193 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$VALIDATION;") : null;
194
195 public static final TypeReference ExceptionTable =
196 (VM.BuildForOptCompiler) ? findOrCreate(org.jikesrvm.compilers.common.ExceptionTable.class) : null;
197
198 public static final TypeReference OptimizationPlanner =
199 (VM.BuildForAdaptiveSystem) ? findOrCreate(org.jikesrvm.compilers.opt.driver.OptimizationPlanner.class) : null;
200
201 /**
202 * Hash value based on name, used for canonical type dictionary
203 */
204 @Override
205 public int hashCode() {
206 return name.hashCode();
207 }
208
209 /**
210 * Are two keys equivalent? Used for canonical type dictionary.
211 * NB ignores id value
212 */
213 @Override
214 public boolean equals(Object other) {
215 if (other instanceof TypeReference) {
216 TypeReference that = (TypeReference) other;
217 return name == that.name && classloader.equals(that.classloader);
218 } else {
219 return false;
220 }
221 }
222
223 /**
224 * Find or create the canonical TypeReference instance for
225 * the given pair.
226 *
227 * @param cl the classloader (defining/initiating depending on usage)
228 * @param tn the name of the type
229 *
230 * @throws IllegalArgumentException Needs to throw some kind of error in
231 * the case of a Atom that does not represent a type name.
232 */
233 public static synchronized TypeReference findOrCreate(ClassLoader cl, Atom tn) throws IllegalArgumentException {
234 TypeDescriptorParsing.validateAsTypeDescriptor(tn);
235 // Primitives, arrays of primitives, system classes and arrays of system
236 // classes must use the bootstrap classloader. Force that here so we don't
237 // have to worry about it anywhere else in the VM.
238 ClassLoader bootstrapCL = BootstrapClassLoader.getBootstrapClassLoader();
239 if (cl == null) {
240 cl = bootstrapCL;
241 } else if (cl != bootstrapCL) {
242 if (tn.isClassDescriptor()) {
243 if (tn.isBootstrapClassDescriptor()) {
244 cl = bootstrapCL;
245 }
246 } else if (tn.isArrayDescriptor()) {
247 Atom innermostElementType = tn.parseForInnermostArrayElementDescriptor();
248 if (innermostElementType.isClassDescriptor()) {
249 if (innermostElementType.isBootstrapClassDescriptor()) {
250 cl = bootstrapCL;
251 }
252 } else {
253 cl = bootstrapCL;
254 }
255 } else {
256 cl = bootstrapCL;
257 }
258 }
259 return findOrCreateInternal(cl, tn);
260 }
261
262 /**
263 * Shorthand for doing a find or create for a type reference that should
264 * be created using the bootstrap classloader.
265 * @param tn type name
266 */
267 public static TypeReference findOrCreate(String tn) {
268 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), Atom.findOrCreateAsciiAtom(tn));
269 }
270
271 /**
272 * Convert a java.lang.Class into a type reference the slow way. For
273 * use in boot image writing
274 * @param klass java.lang.Class to convert to type reference
275 */
276 public static TypeReference findOrCreate(Class<?> klass) {
277 if (VM.runningVM) {
278 return java.lang.JikesRVMSupport.getTypeForClass(klass).getTypeRef();
279 } else {
280 String className = klass.getName();
281 if (className.startsWith("[")) {
282 // an array
283 Atom classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/'));
284 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classAtom);
285 } else {
286 // a class
287 Atom classAtom;
288 if (className.equals("int")) {
289 return TypeReference.Int;
290 } else if (className.equals("boolean")) {
291 return TypeReference.Boolean;
292 } else if (className.equals("byte")) {
293 return TypeReference.Byte;
294 } else if (className.equals("char")) {
295 return TypeReference.Char;
296 } else if (className.equals("double")) {
297 return TypeReference.Double;
298 } else if (className.equals("float")) {
299 return TypeReference.Float;
300 } else if (className.equals("long")) {
301 return TypeReference.Long;
302 } else if (className.equals("short")) {
303 return TypeReference.Short;
304 } else if (className.equals("void")) {
305 return TypeReference.Void;
306 } else {
307 classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/'));
308 }
309 Atom classDescriptor = classAtom.descriptorFromClassName();
310 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor);
311 }
312 }
313 }
314
315 /**
316 * Find or create the canonical TypeReference instance for
317 * the given pair without type descriptor parsing.
318 *
319 * @param cl the classloader (defining/initiating depending on usage)
320 * @param tn the name of the type
321 */
322 public static synchronized TypeReference findOrCreateInternal(ClassLoader cl, Atom tn) {
323 // Next actually findOrCreate the type reference using the proper classloader.
324 TypeReference key = new TypeReference(cl, tn, nextId);
325 TypeReference val = dictionary.get(key);
326 if (val == null) {
327 // Create type reference
328 val = key;
329 nextId++; // id of val is the nextId, move it along
330 int column = val.id >> LOG_ROW_SIZE;
331 if (column == types.length) {
332 // Grow the array of types if necessary
333 TypeReference[][] tmp = new TypeReference[column+1][];
334 for (int i=0; i < column; i++) {
335 tmp[i] = types[i];
336 }
337 types = tmp;
338 types[column] = new TypeReference[1 << LOG_ROW_SIZE];
339 }
340 types[column][val.id & ROW_MASK] = val;
341 dictionary.add(val);
342 }
343 return val;
344 }
345
346 /**
347 * Constructor
348 * @param cl the classloader
349 * @param tn the type name
350 * @param id the numeric identifier
351 */
352 private TypeReference(ClassLoader cl, Atom tn, int id) {
353 classloader = cl;
354 name = tn;
355 this.id = id;
356 }
357
358 /**
359 * Get the cannonical type reference given its id. The unused id of 0 will return null.
360 * @param id the type references id
361 * @return the type reference
362 */
363 @Uninterruptible
364 public static TypeReference getTypeRef(int id) {
365 return types[id >> LOG_ROW_SIZE][id & ROW_MASK];
366 }
367
368 /**
369 * @return the classloader component of this type reference
370 */
371 @Uninterruptible
372 public ClassLoader getClassLoader() {
373 return classloader;
374 }
375
376 /**
377 * @return the type name component of this type reference
378 */
379 @Uninterruptible
380 public Atom getName() {
381 return name;
382 }
383
384 /**
385 * Get the element type of for this array type
386 */
387 public TypeReference getArrayElementType() {
388 if (VM.VerifyAssertions) VM._assert(isArrayType());
389
390 if (isUnboxedArrayType()) {
391 if (this == AddressArray) {
392 return Address;
393 } else if (this == ObjectReferenceArray) {
394 return ObjectReference;
395 } else if (this == WordArray) {
396 return Word;
397 } else if (this == OffsetArray) {
398 return Offset;
399 } else if (this == ExtentArray) {
400 return Extent;
401 } else if (this == CodeArray) {
402 return Code;
403 } else {
404 if (VM.VerifyAssertions) VM._assert(false, "Unexpected case of Magic arrays!");
405 return null;
406 }
407 } else {
408 return findOrCreate(classloader, name.parseForArrayElementDescriptor());
409 }
410 }
411
412 /**
413 * Get array type corresponding to "this" array element type.
414 */
415 public TypeReference getArrayTypeForElementType() {
416 Atom arrayDescriptor = name.arrayDescriptorFromElementDescriptor();
417 return findOrCreate(classloader, arrayDescriptor);
418 }
419
420 /**
421 * Return the dimensionality of the type.
422 * By convention, class types have dimensionality 0,
423 * primitves -1, and arrays the number of [ in their descriptor.
424 */
425 public int getDimensionality() {
426 if (isArrayType()) {
427 TypeReference elem = getArrayElementType();
428 if (elem.isArrayType()) {
429 // NOTE: we must recur instead of attempting to parse
430 // the array descriptor for ['s so we correctly handle
431 // [AddressArray etc. which actually has dimensionality 2!
432 return 1 + elem.getDimensionality();
433 } else {
434 return 1;
435 }
436 } else if (isUnboxedType()) {
437 return -1;
438 } else if (isClassType()) {
439 return 0;
440 } else {
441 return -1;
442 }
443 }
444
445 /**
446 * Return the innermost element type reference for an array
447 */
448 public TypeReference getInnermostElementType() {
449 TypeReference elem = getArrayElementType();
450 if (elem.isArrayType()) {
451 // NOTE: we must recur instead of attempting to parse
452 // the array descriptor for ['s so we correctly handle
453 // [AddressArray and similar evil VMMagic
454 return elem.getInnermostElementType();
455 } else {
456 return elem;
457 }
458 }
459
460 /**
461 * Does 'this' refer to a class?
462 */
463 @Uninterruptible
464 public boolean isClassType() {
465 return name.isClassDescriptor() && !(isUnboxedArrayType() || isUnboxedType());
466 }
467
468 /**
469 * Does 'this' refer to an array?
470 */
471 @Uninterruptible
472 public boolean isArrayType() {
473 return name.isArrayDescriptor() || isUnboxedArrayType();
474 }
475
476 /**
477 * Does 'this' refer to a primitive type
478 */
479 @Uninterruptible
480 public boolean isPrimitiveType() {
481 return !(isArrayType() || isClassType());
482 }
483
484 /**
485 * Does 'this' refer to a reference type
486 */
487 @Uninterruptible
488 public boolean isReferenceType() {
489 return !isPrimitiveType();
490 }
491
492 /**
493 * Does 'this' refer to Word, Address, Offset or Extent
494 */
495 @Uninterruptible
496 public boolean isWordLikeType() {
497 return this == Word || this == Offset || this == Address || this == Extent;
498 }
499
500 /**
501 * Does 'this' refer to Word
502 */
503 @Uninterruptible
504 public boolean isWordType() {
505 return this == Word;
506 }
507
508 /**
509 * Does 'this' refer to Address
510 */
511 @Uninterruptible
512 public boolean isAddressType() {
513 return this == Address;
514 }
515
516 /**
517 * Does 'this' refer to Offset
518 */
519 @Uninterruptible
520 public boolean isOffsetType() {
521 return this == Offset;
522 }
523
524 /**
525 * Does 'this' refer to Extent
526 */
527 @Uninterruptible
528 public boolean isExtentType() {
529 return this == Extent;
530 }
531
532 /**
533 * Does 'this' refer to an unboxed type.
534 */
535 @Uninterruptible
536 public boolean isUnboxedType() {
537 return isWordLikeType() || isCodeType();
538 }
539
540 /**
541 * Does 'this' refer to Code
542 */
543 @Uninterruptible
544 public boolean isCodeType() {
545 return this == Code;
546 }
547
548 /**
549 * Does 'this' refer to WordArray, AddressArray, OffsetArray or ExtentArray
550 */
551 @Uninterruptible
552 public boolean isWordArrayType() {
553 return this == WordArray ||
554 this == OffsetArray ||
555 this == AddressArray ||
556 this == ExtentArray;
557 }
558
559 /**
560 * Does 'this' refer to WordArray, AddressArray, OffsetArray or ExtentArray
561 */
562 @Uninterruptible
563 public boolean isUnboxedArrayType() {
564 return isWordArrayType() || isCodeArrayType() || this == ObjectReferenceArray;
565 }
566
567 /**
568 * Does 'this' refer to a runtime table type?
569 */
570 @Uninterruptible
571 public boolean isRuntimeTable() {
572 return this == IMT || this == TIB || this == ITable || this == ITableArray ||
573 this == FunctionTable || this == LinkageTripletTable;
574 }
575
576 /**
577 * Does 'this' refer to CodeArray
578 */
579 @Uninterruptible
580 public boolean isCodeArrayType() {
581 return this == CodeArray;
582 }
583
584 /**
585 * Does 'this' refer to Magic?
586 */
587 @Uninterruptible
588 public boolean isMagicType() {
589 return this == Magic || isUnboxedType() || isUnboxedArrayType() || this == ObjectReference || isRuntimeTable();
590 }
591
592 /**
593 * How many java stack/local words do value of this type take?
594 */
595 @Uninterruptible
596 public int getStackWords() {
597 if (isLoaded()) {
598 // all primitive and magic types are resolved immediately
599 return type.getStackWords();
600 } else {
601 // anything remaining must be a reference
602 return 1;
603 }
604 }
605
606 /**
607 * How many bytes do values of this type take?
608 */
609 @Uninterruptible
610 public int getMemoryBytes() {
611 if (isLoaded()) {
612 // all primitive and magic types are resolved immediately
613 return type.getMemoryBytes();
614 } else {
615 // anything remaining must be a reference
616 return BYTES_IN_ADDRESS;
617 }
618 }
619
620 /**
621 * @return the id to use for this type
622 */
623 @Uninterruptible
624 public int getId() {
625 return id;
626 }
627
628 /**
629 * Is this the type reference for the void primitive type?
630 */
631 @Uninterruptible
632 public boolean isVoidType() {
633 return this == Void;
634 }
635
636 /**
637 * Is this the type reference for the boolean primitive type?
638 */
639 @Uninterruptible
640 public boolean isBooleanType() {
641 return this == Boolean;
642 }
643
644 /**
645 * Is this the type reference for the byte primitive type?
646 */
647 @Uninterruptible
648 public boolean isByteType() {
649 return this == Byte;
650 }
651
652 /**
653 * Is this the type reference for the short primitive type?
654 */
655 @Uninterruptible
656 public boolean isShortType() {
657 return this == Short;
658 }
659
660 /**
661 * Is this the type reference for the char primitive type?
662 */
663 @Uninterruptible
664 public boolean isCharType() {
665 return this == Char;
666 }
667
668 /**
669 * Is this the type reference for the int primitive type?
670 */
671 @Uninterruptible
672 public boolean isIntType() {
673 return this == Int;
674 }
675
676 /**
677 * Is this the type reference for the long primitive type?
678 */
679 @Uninterruptible
680 public boolean isLongType() {
681 return this == Long;
682 }
683
684 /**
685 * Is this the type reference for the float primitive type?
686 */
687 @Uninterruptible
688 public boolean isFloatType() {
689 return this == Float;
690 }
691
692 /**
693 * Is this the type reference for the double primitive type?
694 */
695 @Uninterruptible
696 public boolean isDoubleType() {
697 return this == Double;
698 }
699
700 /**
701 * Is <code>this</code> the type reference for an
702 * int-like (1, 8, 16, or 32 bit integral) primitive type?
703 */
704 @Uninterruptible
705 public boolean isIntLikeType() {
706 return isBooleanType() || isByteType() || isCharType() || isShortType() || isIntType();
707 }
708
709 /**
710 * Do this and that definitely refer to the different types?
711 */
712 public boolean definitelyDifferent(TypeReference that) {
713 if (this == that) return false;
714 if (name != that.name) return true;
715 RVMType mine = peekType();
716 RVMType theirs = that.peekType();
717 if (mine == null || theirs == null) return false;
718 return mine != theirs;
719 }
720
721 /**
722 * Do this and that definitely refer to the same type?
723 */
724 public boolean definitelySame(TypeReference that) {
725 if (VM.VerifyAssertions) VM._assert(that != null);
726 if (this == that) return true;
727 if (name != that.name) return false;
728 RVMType mine = peekType();
729 RVMType theirs = that.peekType();
730 if (mine == null || theirs == null) return false;
731 return mine == theirs;
732 }
733
734 /**
735 * Return true if the type for type reference has been loaded.
736 */
737 @Uninterruptible
738 public boolean isLoaded() {
739 return type != null;
740 }
741
742 /**
743 * Return true if the type for type reference has been loaded and it is resolved.
744 */
745 @Uninterruptible
746 public boolean isResolved() {
747 return isLoaded() && type.isResolved();
748 }
749
750 /**
751 * @return the current value of resolvedType -- null if not yet resolved.
752 */
753 @Uninterruptible
754 public RVMType peekType() {
755 return type;
756 }
757
758 /*
759 * for use by RVMClassLoader.defineClassInternal
760 */
761 void setType(RVMType rt) {
762 type = rt;
763 if (type.isClassType()) {
764 type.asClass().setResolvedMembers();
765 }
766 }
767
768 /**
769 * Force the resolution of the type reference. May cause class loading
770 * if a required class file hasn't been loaded before.
771 *
772 * @return the RVMType instance that this references resolves to.
773 *
774 * @throws NoClassDefFoundError When it cannot resolve a class.
775 * we go to the trouble of converting the class loader's
776 * <code>ClassNotFoundException</code> into this error,
777 * since we need to be able to throw
778 * <code>NoClassDefFoundError</code> for classes
779 * that we're loading whose existence was compile-time checked.
780 *
781 * @throws IllegalArgumentException In case of a malformed class name
782 * (should never happen, since the right thing to do is probably to
783 * validate them as soon as we insert them into a TypeReference.
784 * This stinks. XXX)
785 */
786 public RVMType resolve() throws NoClassDefFoundError, IllegalArgumentException {
787 /*
788 * Lock the classloader instead of this to avoid conflicting locking order.
789 * Suppose we locked this, then one thread could call resolve(), locking this,
790 * call classloader.loadClass(), trying to lock the classloader. Meanwhile,
791 * another thread could call loadClass(), locking the classloader, then
792 * try to resolve() the TypeReference, resulting in a deadlock
793 */
794 synchronized (classloader) {
795 return resolveInternal();
796 }
797 }
798
799 private RVMType resolveInternal() throws NoClassDefFoundError, IllegalArgumentException {
800 if (type != null) return type;
801 if (isClassType()) {
802 RVMType ans;
803 if (VM.runningVM) {
804 Class<?> klass;
805 String myName = name.classNameFromDescriptor();
806 try {
807 klass = classloader.loadClass(myName);
808 } catch (ClassNotFoundException cnf) {
809 NoClassDefFoundError ncdfe =
810 new NoClassDefFoundError("Could not find the class " + myName + ":\n\t" + cnf.getMessage());
811 ncdfe.initCause(cnf); // in dubious taste, but helps us debug Jikes RVM
812 throw ncdfe;
813 }
814
815 ans = java.lang.JikesRVMSupport.getTypeForClass(klass);
816 } else {
817 // Use a special purpose backdoor to avoid creating java.lang.Class
818 // objects when not running the VM (we get host JDK Class objects
819 // and that just doesn't work).
820 ans = ((BootstrapClassLoader) classloader).loadVMClass(name.classNameFromDescriptor());
821 }
822 if (VM.VerifyAssertions) {
823 VM._assert(type == null || type == ans);
824 }
825 setType(ans);
826 } else if (isArrayType()) {
827 if (isUnboxedArrayType()) {
828 // Ensure that we only create one RVMArray object for each pair of
829 // names for this type.
830 // Do this by resolving AddressArray to [Address
831 setType(getArrayElementType().getArrayTypeForElementType().resolve());
832 } else {
833 RVMType elementType = getArrayElementType().resolve();
834 if (elementType.getClassLoader() != classloader) {
835 // We aren't the canonical type reference because the element type
836 // was loaded using a different classloader.
837 // Find the canonical type reference and ask it to resolve itself.
838 TypeReference canonical = TypeReference.findOrCreate(elementType.getClassLoader(), name);
839 setType(canonical.resolve());
840 } else {
841 setType(new RVMArray(this, elementType));
842 }
843 }
844 } else {
845 if (isUnboxedType()) {
846 setType(UnboxedType.createUnboxedType(this));
847 } else {
848 setType(Primitive.createPrimitive(this));
849 }
850 }
851 return type;
852 }
853
854 @Override
855 public String toString() {
856 return "< " + classloader + ", " + name + " >";
857 }
858 }