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 */ 013package org.jikesrvm.classloader; 014 015import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_ABSTRACT; 016import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_ANNOTATION; 017import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_ENUM; 018import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_FINAL; 019import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_INTERFACE; 020import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_PUBLIC; 021import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_STATIC; 022import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_SUPER; 023import static org.jikesrvm.classloader.ClassLoaderConstants.ACC_SYNTHETIC; 024import static org.jikesrvm.classloader.ClassLoaderConstants.APPLICABLE_TO_CLASSES; 025import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_INITIALIZED; 026import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_INITIALIZER_FAILED; 027import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_INITIALIZING; 028import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_INSTANTIATED; 029import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_LOADED; 030import static org.jikesrvm.classloader.ClassLoaderConstants.CLASS_RESOLVED; 031import static org.jikesrvm.classloader.ClassLoaderConstants.CP_MEMBER; 032import static org.jikesrvm.classloader.ClassLoaderConstants.CP_UTF; 033import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE; 034import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT; 035import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_LONG; 036import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS; 037 038import java.lang.annotation.Annotation; 039import java.lang.annotation.Inherited; 040 041import org.jikesrvm.VM; 042import org.jikesrvm.compilers.common.CompiledMethod; 043import org.jikesrvm.compilers.opt.inlining.ClassLoadingDependencyManager; 044import org.jikesrvm.mm.mminterface.AlignmentEncoding; 045import org.jikesrvm.mm.mminterface.HandInlinedScanning; 046import org.jikesrvm.mm.mminterface.MemoryManager; 047import org.jikesrvm.objectmodel.FieldLayoutContext; 048import org.jikesrvm.objectmodel.IMT; 049import org.jikesrvm.objectmodel.ObjectModel; 050import org.jikesrvm.objectmodel.TIB; 051import org.jikesrvm.runtime.Callbacks; 052import org.jikesrvm.runtime.Magic; 053import org.jikesrvm.runtime.RuntimeEntrypoints; 054import org.jikesrvm.runtime.StackBrowser; 055import org.jikesrvm.runtime.Statics; 056import org.vmmagic.pragma.NonMoving; 057import org.vmmagic.pragma.Pure; 058import org.vmmagic.pragma.Uninterruptible; 059import org.vmmagic.unboxed.Offset; 060 061/** 062 * Description of a java "class" type.<p> 063 * 064 * This description is read from a ".class" file as classes/field/methods 065 * referenced by the running program need to be bound in to the running image. 066 * 067 * @see RVMType 068 * @see RVMArray 069 * @see Primitive 070 * @see UnboxedType 071 */ 072@NonMoving 073public final class RVMClass extends RVMType { 074 075 /** Flag for closed world testing */ 076 private static boolean classLoadingDisabled = false; 077 078 /** 079 * The constant pool holds constants used by the class and the Java 080 * bytecodes in the methods associated with this class. This 081 * constant pool isn't that from the class file, instead it has been 082 * processed during class loading (see {@link ClassFileReader#readClass}). The loaded 083 * class' constant pool has 3 bits of type information (such as 084 * (see {@link ClassLoaderConstants#CP_INT})), the rest of the int holds data as follows: 085 * 086 * <ul> 087 * <li>utf: value is a UTF atom identifier</li> 088 * <li>int, long, float, double, string: value is an offset in the 089 * JTOC</li> 090 * <li>member: value is a member reference identifier</li> 091 * <li>class: value is a type reference identifier. NB this means 092 * that class literal bytecodes must first convert the identifier 093 * in to a JTOC offset.</li> 094 * </ul> 095 */ 096 private final int[] constantPool; 097 /** {@link ClassLoaderConstants} */ 098 private final short modifiers; 099 /** Super class of this class */ 100 private final RVMClass superClass; 101 /** 102 * Non-final list of sub-classes. Classes added as sub-classes are 103 * loaded. 104 */ 105 private RVMClass[] subClasses; 106 /** Interfaces supported by this class */ 107 private final RVMClass[] declaredInterfaces; 108 /** Fields of this class */ 109 private final RVMField[] declaredFields; 110 /** Methods of this class */ 111 private final RVMMethod[] declaredMethods; 112 /** Declared inner classes, may be null */ 113 private final TypeReference[] declaredClasses; 114 /** The outer class, or null if this is not a inner/nested class */ 115 private final TypeReference declaringClass; 116 /** The enclosing class if this is a local class */ 117 private final TypeReference enclosingClass; 118 /** The enclosing method if this is a local class */ 119 private final MethodReference enclosingMethod; 120 /** Name of file .class file was compiled from, may be null */ 121 private final Atom sourceName; 122 /** 123 * The signature is a string representing the generic type for this 124 * class declaration, may be null 125 */ 126 private final Atom signature; 127 /** 128 * Class initializer method, null if no method or if class is 129 * initialized (ie class initializer method has been run) 130 */ 131 private RVMMethod classInitializerMethod; 132 133 /** 134 * current class-loading stage (loaded, resolved, instantiated, 135 * initializing or initialized) 136 */ 137 private byte state; 138 139 // 140 // The following are valid only when "state >= CLASS_RESOLVED". 141 // 142 143 // --- Field size and offset information --- // 144 145 /** fields shared by all instances of class */ 146 private RVMField[] staticFields; 147 148 /** fields distinct for each instance of class */ 149 private RVMField[] instanceFields; 150 151 /** Total size of per-instance data, in bytes */ 152 private int instanceSize; 153 154 /** The desired alignment for instances of this type. */ 155 private int alignment; 156 157 /** 158 * A field layout helper - used to keep context regarding field layouts. 159 * Managed by the field layout objects in the ObjectModel. 160 */ 161 private FieldLayoutContext fieldLayoutContext = null; 162 163 // --- Method-dispatching information --- // 164 165 /** static methods of class */ 166 private RVMMethod[] staticMethods; 167 168 /** constructor methods of class */ 169 private RVMMethod[] constructorMethods; 170 171 /** virtual methods of class */ 172 private RVMMethod[] virtualMethods; 173 174 /** 175 * Do objects of this class have a finalizer method? 176 */ 177 private boolean hasFinalizer; 178 179 /** type and virtual method dispatch table for class */ 180 private TIB typeInformationBlock; 181 182 // --- Memory manager support --- // 183 184 /** 185 * Is this class type in the bootimage? Types in the boot image can 186 * be initialized prior to execution (therefore removing runtime 187 * resolution). 188 */ 189 private boolean inBootImage; 190 191 /** 192 * At what offset is the thin lock word to be found in instances of 193 * objects of this type? A value of -1 indicates that the instances of 194 * this type do not have inline thin locks. 195 */ 196 private Offset thinLockOffset; 197 198 /** Reference Count GC: is this type acyclic? */ 199 private boolean acyclic; 200 201 /** Cached set of inherited and declared annotations. */ 202 private Annotation[] annotations; 203 204 /** Set of objects that are cached here to ensure they are not collected by GC **/ 205 private Object[] objectCache; 206 207 /** The imt for this class **/ 208 @SuppressWarnings("unused") 209 private IMT imt; 210 211 // --- Assertion support --- // 212 /** 213 * Are assertions enabled on this class? 214 */ 215 private final boolean desiredAssertionStatus; 216 217 // --- General purpose functions --- // 218 219 /** 220 * Name - something like "java.lang.String". 221 */ 222 @Override 223 @Pure 224 public String toString() { 225 return getDescriptor().classNameFromDescriptor(); 226 } 227 228 /** 229 * Package name - something like "java.lang". 230 * @return package name or the empty string if the class is a member of the unnamed package 231 */ 232 public String getPackageName() { 233 String className = toString(); 234 int lastDot = className.lastIndexOf('.'); 235 return (lastDot >= 0) ? className.substring(0, lastDot) : ""; 236 } 237 238 /** 239 * @return 1 240 */ 241 @Override 242 @Pure 243 @Uninterruptible 244 public int getStackWords() { 245 return 1; 246 } 247 248 @Override 249 @Pure 250 @Uninterruptible 251 public int getMemoryBytes() { 252 return BYTES_IN_ADDRESS; 253 } 254 255 /** 256 * @return {@code true} if "this" is an "interface" description rather than a "class" description 257 */ 258 @Uninterruptible 259 public boolean isInterface() { 260 return (modifiers & ACC_INTERFACE) != 0; 261 } 262 263 /** 264 * @return whether "this" is usable from other packages 265 */ 266 @Uninterruptible 267 public boolean isPublic() { 268 return (modifiers & ACC_PUBLIC) != 0; 269 } 270 271 /** 272 * @return {@code true} if "this" is non-subclassable 273 */ 274 @Uninterruptible 275 public boolean isFinal() { 276 return (modifiers & ACC_FINAL) != 0; 277 } 278 279 /** 280 * @return {@code true} if "this" is non-instantiable 281 */ 282 @Uninterruptible 283 public boolean isAbstract() { 284 return (modifiers & ACC_ABSTRACT) != 0; 285 } 286 287 /** 288 * @return {@code true} if "this" uses new-style "invokespecial" semantics for method calls in this class 289 */ 290 @Uninterruptible 291 public boolean isSpecial() { 292 return (modifiers & ACC_SUPER) != 0; 293 } 294 295 /** 296 * @return {@code true} if "this" is not present in source code file 297 */ 298 public boolean isSynthetic() { 299 return (modifiers & ACC_SYNTHETIC) != 0; 300 } 301 302 /** 303 * @return {@code true} if "this" is an enumeration 304 */ 305 public boolean isEnum() { 306 return (modifiers & ACC_ENUM) != 0; 307 } 308 309 /** 310 * @return {@code true} if "this" is an annotation type 311 */ 312 public boolean isAnnotation() { 313 return (modifiers & ACC_ANNOTATION) != 0; 314 } 315 316 /** 317 * @return {@code true} if this is a representation of an anonymous class 318 */ 319 public boolean isAnonymousClass() { 320 if (enclosingClass == null || enclosingClass.peekType() == null) return false; 321 for (TypeReference t: enclosingClass.peekType().asClass().getDeclaredClasses()) { 322 if (t == typeRef) return false; 323 } 324 return true; 325 } 326 327 /** 328 * @return {@code true} if this is a representation of a local class, ie 329 * local to a block of code. 330 */ 331 public boolean isLocalClass() { 332 return enclosingMethod != null; 333 } 334 335 /** 336 * @return {@code true} if this is a representation of a member class 337 */ 338 public boolean isMemberClass() { 339 return ((declaringClass != null) && ((modifiers & ACC_STATIC) == 0)); 340 } 341 /** 342 * @return {@code true} if this an object of this class could be assigned to Throwable 343 */ 344 public boolean isThrowable() { 345 return (getTypeRef() == TypeReference.JavaLangThrowable) || 346 RuntimeEntrypoints.isAssignableWith(TypeReference.JavaLangThrowable.resolve(), this); 347 } 348 /** 349 * Get the modifiers associated with this class {@link 350 * ClassLoaderConstants}. 351 * 352 * @return the modifiers of "this" 353 */ 354 public int getModifiers() { 355 return modifiers & APPLICABLE_TO_CLASSES; 356 } 357 358 /** 359 * @return generic type information for class 360 */ 361 public Atom getSignature() { 362 return signature; 363 } 364 365 /** 366 * @return Name of source file from which class was compiled - 367 * something like "c:\java\src\java\lang\Object.java". 368 * ({@code null} --> "unknown - wasn't recorded by compiler"). 369 */ 370 public Atom getSourceName() { 371 return sourceName; 372 } 373 374 /** 375 * @return superclass of this class ({@code null} means "no superclass", 376 * i.e. class is "java/lang/Object"). 377 */ 378 @Uninterruptible 379 public RVMClass getSuperClass() { 380 return superClass; 381 } 382 383 /** 384 * @return currently loaded classes that "extend" this class. 385 */ 386 @Uninterruptible 387 public RVMClass[] getSubClasses() { 388 return subClasses; 389 } 390 391 /** 392 * @return interfaces implemented directly by this class 393 * (ie. not including superclasses). 394 */ 395 @Uninterruptible 396 public RVMClass[] getDeclaredInterfaces() { 397 return declaredInterfaces; 398 } 399 400 /** 401 * @return fields defined directly by this class (i.e. not including superclasses). 402 */ 403 @Uninterruptible 404 public RVMField[] getDeclaredFields() { 405 return declaredFields; 406 } 407 408 /** 409 * Does this class directly define a final instance field (has implications for JMM). 410 * 411 * @return {@code true} if this class declares a final instance field 412 */ 413 public boolean declaresFinalInstanceField() { 414 for (RVMField f : declaredFields) { 415 if (f.isFinal() && !f.isStatic()) return true; 416 } 417 return false; 418 } 419 420 /** 421 * @return methods defined directly by this class (i.e. not including superclasses). 422 */ 423 @Uninterruptible 424 public RVMMethod[] getDeclaredMethods() { 425 return declaredMethods; 426 } 427 428 /** 429 * @return declared inner and static member classes 430 */ 431 public TypeReference[] getDeclaredClasses() { 432 return declaredClasses; 433 } 434 435 /** 436 * @return class that declared this class, or {@code null} if this is not an 437 * inner/nested class. 438 */ 439 public TypeReference getDeclaringClass() { 440 return declaringClass; 441 } 442 443 /** 444 * @return class that immediately encloses this class, or {@code null} if this is not an 445 * inner/nested class. 446 */ 447 public TypeReference getEnclosingClass() { 448 return enclosingClass; 449 } 450 451 /** 452 * Sets the resolvedMember in all declared members. 453 */ 454 void setResolvedMembers() { 455 for (RVMField field: declaredFields) { 456 /* Make all declared fields appear resolved */ 457 field.getMemberRef().asFieldReference().setResolvedMember(field); 458 } 459 for (RVMMethod method: declaredMethods) { 460 /* Make all declared methods appear resolved */ 461 method.getMemberRef().asMethodReference().setResolvedMember(method); 462 } 463 if (virtualMethods != null) { 464 /* Possibly created Miranda methods */ 465 for (RVMMethod method: virtualMethods) { 466 if (method.getDeclaringClass() == this) { 467 method.getMemberRef().asMethodReference().setResolvedMember(method); 468 } 469 } 470 } 471 } 472 473 /** 474 * @return static initializer method for this class ({@code null} -> no static initializer 475 * or initializer already been run). 476 */ 477 @Uninterruptible 478 public RVMMethod getClassInitializerMethod() { 479 return classInitializerMethod; 480 } 481 482 @Override 483 Annotation[] getAnnotationsInternal() { 484 final RVMClass parent = getSuperClass(); 485 if (parent == null) { 486 return super.getAnnotationsInternal(); 487 } 488 if (annotations == null) { 489 final Annotation[] declared = getDeclaredAnnotations(); 490 // Not synchronized as it does not matter if occasionally we create two cached copies 491 final Annotation[] parentAnnotations = parent.getAnnotations(); 492 int rejected = 0; 493 for (int i = 0; i < parentAnnotations.length; i++) { 494 final Annotation pa = parentAnnotations[i]; 495 final Class<? extends Annotation> paType = pa.annotationType(); 496 if (!paType.isAnnotationPresent(Inherited.class)) { 497 parentAnnotations[i] = null; 498 rejected++; 499 } else { 500 for (final Annotation a : declared) { 501 if (a.annotationType().equals(paType)) { 502 parentAnnotations[i] = null; 503 rejected++; 504 break; 505 } 506 } 507 } 508 } 509 final Annotation[] cache = new Annotation[declared.length + parentAnnotations.length - rejected]; 510 System.arraycopy(declared, 0, cache, 0, declared.length); 511 int index = declared.length; 512 for (final Annotation pa : parentAnnotations) { 513 if (pa != null) cache[index++] = pa; 514 } 515 annotations = cache; 516 } 517 return annotations; 518 } 519 520 /** 521 * Find description of a field of this class. 522 * @param fieldName field name - something like "foo" 523 * @param fieldDescriptor field descriptor - something like "I" 524 * @return description ({@code null} --> not found) 525 */ 526 public RVMField findDeclaredField(Atom fieldName, Atom fieldDescriptor) { 527 for (RVMField field : declaredFields) { 528 if (field.getName() == fieldName && field.getDescriptor() == fieldDescriptor) { 529 return field; 530 } 531 } 532 return null; 533 } 534 535 /** 536 * Find description of a field of this class. NB. ignores descriptor. 537 * @param fieldName field name - something like "foo" 538 * @return description ({@code null} --> not found) 539 */ 540 public RVMField findDeclaredField(Atom fieldName) { 541 for (RVMField field : declaredFields) { 542 if (field.getName() == fieldName) { 543 return field; 544 } 545 } 546 return null; 547 } 548 549 /** 550 * Find description of a method of this class. 551 * @param methodName method name - something like "foo" 552 * @param methodDescriptor method descriptor - something like "()I" 553 * @return description (null --> not found) 554 */ 555 public RVMMethod findDeclaredMethod(Atom methodName, Atom methodDescriptor) { 556 for (RVMMethod method : declaredMethods) { 557 if (method.getName() == methodName && method.getDescriptor() == methodDescriptor) { 558 return method; 559 } 560 } 561 return null; 562 } 563 564 /** 565 * Find the first description of a method of this class. 566 * @param methodName method name - something like "foo" 567 * @return description (null --> not found) 568 */ 569 public RVMMethod findDeclaredMethod(Atom methodName) { 570 for (RVMMethod method : declaredMethods) { 571 if (method.getName() == methodName) { 572 return method; 573 } 574 } 575 return null; 576 } 577 578 /** 579 * Find description of "public static void main(String[])" 580 * method of this class. 581 * @return description ({@code null} --> not found) 582 */ 583 public RVMMethod findMainMethod() { 584 Atom mainName = Atom.findOrCreateAsciiAtom(("main")); 585 Atom mainDescriptor = Atom.findOrCreateAsciiAtom(("([Ljava/lang/String;)V")); 586 RVMMethod mainMethod = this.findDeclaredMethod(mainName, mainDescriptor); 587 588 if (mainMethod == null || !mainMethod.isPublic() || !mainMethod.isStatic()) { 589 // no such method 590 return null; 591 } 592 return mainMethod; 593 } 594 595 public synchronized void addCachedObject(Object o) { 596 Object[] newObjectCache; 597 if (objectCache == null) { 598 newObjectCache = new Object[1]; 599 } else { 600 newObjectCache = new Object[objectCache.length + 1]; 601 for (int i = 0; i < objectCache.length; i++) { 602 newObjectCache[i] = objectCache[i]; 603 } 604 } 605 newObjectCache[newObjectCache.length - 1] = o; 606 objectCache = newObjectCache; 607 } 608 609 public void setIMT(IMT imt) { 610 this.imt = imt; 611 } 612 613 // 614 // Constant pool accessors. 615 // 616 // The constant pool holds literals and external references used by 617 // the bytecodes of this class's methods. 618 // Items are fetched by specifying their "constant pool index". 619 // 620 621 /** 622 * Get offset of a literal constant, in bytes. 623 * Offset is with respect to virtual machine's "table of contents" JTOC). 624 * 625 * @param constantPoolIndex index into the constant pool 626 * @return offset of the literal constant to the JTOC, in bytes 627 */ 628 public Offset getLiteralOffset(int constantPoolIndex) { 629 return ClassFileReader.getLiteralOffset(this.constantPool, constantPoolIndex); 630 } 631 632 public byte getLiteralDescription(int constantPoolIndex) { 633 int cpValue = constantPool[constantPoolIndex]; 634 byte type = ClassFileReader.unpackCPType(cpValue); 635 return type; 636 } 637 638 @Uninterruptible 639 public TypeReference getTypeRef(int constantPoolIndex) { 640 return ClassFileReader.getTypeRef(constantPool, constantPoolIndex); 641 } 642 643 @Uninterruptible 644 public MethodReference getMethodRef(int constantPoolIndex) { 645 return ClassFileReader.getMethodRef(constantPool, constantPoolIndex); 646 } 647 648 @Uninterruptible 649 public FieldReference getFieldRef(int constantPoolIndex) { 650 int cpValue = constantPool[constantPoolIndex]; 651 if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == CP_MEMBER); 652 return (FieldReference) MemberReference.getMemberRef(ClassFileReader.unpackUnsignedCPValue(cpValue)); 653 } 654 655 @Uninterruptible 656 Atom getUtf(int constantPoolIndex) { 657 int cpValue = constantPool[constantPoolIndex]; 658 if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == CP_UTF); 659 return Atom.getAtom(ClassFileReader.unpackUnsignedCPValue(cpValue)); 660 } 661 662 /** 663 * Should the methods of this class be compiled with special 664 * register save/restore logic? 665 * @see org.vmmagic.pragma.DynamicBridge 666 * 667 * @return {@code true} if the methods needs special logic for 668 * register saves and restores 669 */ 670 @Uninterruptible 671 public boolean hasDynamicBridgeAnnotation() { 672 return isAnnotationDeclared(TypeReference.DynamicBridge); 673 } 674 675 /** 676 * The methods of this class are only called from native code, 677 * they are compiled with 678 * a special prolog to interface with the native stack frame. 679 * 680 * @return {@code true} if the methods of this class can only 681 * be called from native code 682 */ 683 @Uninterruptible 684 public boolean hasBridgeFromNativeAnnotation() { 685 return isAnnotationDeclared(TypeReference.NativeBridge); 686 } 687 688 /** 689 * Should the methods of this class save incoming registers ? 690 * @see org.vmmagic.pragma.SaveVolatile 691 * 692 * @return {@code true} if all volatile registers need to be saved 693 * when methods of this class are called 694 */ 695 public boolean hasSaveVolatileAnnotation() { 696 return isAnnotationDeclared(TypeReference.SaveVolatile); 697 } 698 699 //--------------------------------------------------------------------// 700 // The following are available after the class has been "resolved". // 701 //--------------------------------------------------------------------// 702 703 /** 704 * @return {@code true} if this class overrides {@code java.lang.Object.finalize()} 705 */ 706 @Override 707 @Pure 708 @Uninterruptible 709 public boolean hasFinalizer() { 710 if (VM.VerifyAssertions) VM._assert(isResolved()); 711 return hasFinalizer; 712 } 713 714 @Override 715 @Pure 716 public RVMField[] getStaticFields() { 717 if (VM.VerifyAssertions) VM._assert(isResolved()); 718 return staticFields; 719 } 720 721 /** 722 * @return non-static fields of this class (composed with supertypes, if any). 723 * Values in these fields are distinct for each class instance. 724 */ 725 @Override 726 @Pure 727 public RVMField[] getInstanceFields() { 728 if (VM.VerifyAssertions) VM._assert(isResolved()); 729 return instanceFields; 730 } 731 732 @Override 733 @Pure 734 public RVMMethod[] getStaticMethods() { 735 if (VM.VerifyAssertions) VM._assert(isResolved()); 736 return staticMethods; 737 } 738 739 /** 740 * @return constructors ({@code <init>}) methods of this class. 741 */ 742 @Pure 743 public RVMMethod[] getConstructorMethods() { 744 if (VM.VerifyAssertions) { 745 boolean isResolved = isResolved(); 746 if (!isResolved) { 747 String msg = "Error class " + this + " is not resolved but " + state; 748 VM._assert(VM.NOT_REACHED, msg); 749 } 750 } 751 752 return constructorMethods; 753 } 754 755 /** 756 * @return virtually dispatched methods of this class 757 * (composed with supertypes, if any). 758 */ 759 @Override 760 @Pure 761 public RVMMethod[] getVirtualMethods() { 762 if (VM.VerifyAssertions) VM._assert(isResolved()); 763 return virtualMethods; 764 } 765 766 /** 767 * @return All of the interfaces implemented by this class either 768 * directly or by inheritance from superclass and superinterfaces 769 * recursively. 770 */ 771 @Pure 772 public RVMClass[] getAllImplementedInterfaces() { 773 if (VM.VerifyAssertions) VM._assert(isResolved()); 774 int count = 0; 775 int[] doesImplement = getDoesImplement(); 776 for (int mask : doesImplement) { 777 while (mask != 0) { 778 count++; 779 mask &= (mask - 1); // clear lsb 1 bit 780 } 781 } 782 if (count == 0) return emptyVMClass; 783 RVMClass[] ans = new RVMClass[count]; 784 for (int i = 0, idx = 0; i < doesImplement.length; i++) { 785 int mask = doesImplement[i]; 786 if (mask != 0) { 787 for (int j = 0; j < 32; j++) { 788 if ((mask & (1 << j)) != 0) { 789 int id = 32 * i + j; 790 ans[idx++] = RVMClass.getInterface(id); 791 } 792 } 793 } 794 } 795 return ans; 796 } 797 798 /** 799 * @return total size, in bytes, of an instance of this class 800 * (including object header). Note that the class must be resolved 801 * for this information to be available. 802 */ 803 @Uninterruptible 804 public int getInstanceSize() { 805 if (VM.VerifyAssertions) VM._assert(isResolved()); 806 return instanceSize; 807 } 808 809 /** 810 * @return total size, in bytes, of an instance of this class (including 811 * object header). Doesn't perform any verification. 812 */ 813 @Uninterruptible 814 public int getInstanceSizeInternal() { 815 return instanceSize; 816 } 817 818 /** 819 * Set the size of the instance. Only meant to be called from 820 * ObjectModel et al. must be called when lock on class object 821 * is already held (ie from resolve). 822 * 823 * @param size computed size for instances of this class 824 */ 825 @Uninterruptible 826 public void setInstanceSizeInternal(int size) { 827 instanceSize = size; 828 } 829 830 /** 831 * @return number of fields that are non-final 832 */ 833 public int getNumberOfNonFinalReferences() { 834 int count = 0; 835 for (RVMField field: declaredFields) { 836 if (!field.isFinal()) { 837 count++; 838 } 839 } 840 return count; 841 } 842 843 public FieldLayoutContext getFieldLayoutContext() { 844 return fieldLayoutContext; 845 } 846 847 public void setFieldLayoutContext(FieldLayoutContext newLayout) { 848 fieldLayoutContext = isFinal() ? null : newLayout; 849 } 850 851 /** 852 * @return alignment for instances of this class type, in bytes 853 */ 854 @Uninterruptible 855 public int getAlignment() { 856 if (BYTES_IN_ADDRESS == BYTES_IN_DOUBLE) { 857 return BYTES_IN_ADDRESS; 858 } else { 859 return alignment; 860 } 861 } 862 863 public void setAlignment(int align) { 864 if (BYTES_IN_ADDRESS != BYTES_IN_DOUBLE) { 865 if (VM.VerifyAssertions) VM._assert(align >= alignment); 866 alignment = align; 867 } 868 } 869 870 /** 871 * Find specified static method description. 872 * @param memberName method name - something like "foo" 873 * @param memberDescriptor method descriptor - something like "I" or "()I" 874 * @return method description (null --> not found) 875 */ 876 @Pure 877 public RVMMethod findStaticMethod(Atom memberName, Atom memberDescriptor) { 878 if (VM.VerifyAssertions) VM._assert(isResolved()); 879 for (RVMMethod method : getStaticMethods()) { 880 if (method.getName() == memberName && method.getDescriptor() == memberDescriptor) { 881 return method; 882 } 883 } 884 return null; 885 } 886 887 /** 888 * Find specified initializer method description. 889 * @param memberDescriptor init method descriptor - something like "(I)V" 890 * @return method description (null --> not found) 891 */ 892 @Pure 893 public RVMMethod findInitializerMethod(Atom memberDescriptor) { 894 if (VM.VerifyAssertions) VM._assert(isResolved()); 895 for (RVMMethod method : getConstructorMethods()) { 896 if (method.getDescriptor() == memberDescriptor) { 897 return method; 898 } 899 } 900 return null; 901 } 902 903 /** 904 * Runtime type information for this class type. 905 */ 906 @Override 907 @Uninterruptible 908 public TIB getTypeInformationBlock() { 909 if (VM.VerifyAssertions) VM._assert(isResolved()); 910 return typeInformationBlock; 911 } 912 913 //--------------------------------------------------------------------// 914 // Miscellaneous queries. // 915 //---------------------------------------------------------------------// 916 917 /** 918 * Support for user-written class loaders: 919 * It's required to find the classloader of the class 920 * whose method requires another class to be loaded; 921 * the initiating loader of the required class is the 922 * defining loader of the requiring class. 923 * 924 * 925 * @param skip specifies the number of frames back from the 926 * caller to the method whose class's loader is required 927 * 928 * @return the class loader 929 */ 930 public static ClassLoader getClassLoaderFromStackFrame(int skip) { 931 skip++; // account for stack frame of this function 932 StackBrowser browser = new StackBrowser(); 933 VM.disableGC(); 934 browser.init(); 935 while (skip-- > 0) browser.up(); 936 VM.enableGC(); 937 return browser.getClassLoader(); 938 } 939 940 /** 941 * Used for accessibility checks in reflection code. 942 * Find the class of the method that corresponds to the requested frame. 943 * 944 * @param skip Specifies the number of frames back from the 945 * caller to the method whose class is required 946 * 947 * @return the class that declares the method at the desired frame 948 */ 949 public static RVMClass getClassFromStackFrame(int skip) { 950 skip++; // account for stack frame of this function 951 StackBrowser browser = new StackBrowser(); 952 VM.disableGC(); 953 browser.init(); 954 while (skip-- > 0) browser.up(); 955 VM.enableGC(); 956 return browser.getCurrentClass(); 957 } 958 959 /** 960 * @return whether or not assertions should be enabled 961 */ 962 @Override 963 @Pure 964 public boolean getDesiredAssertionStatus() { 965 return desiredAssertionStatus; 966 } 967 968 //--------------------------------------------------------------------// 969 // Load, Resolve, Instantiate, and Initialize // 970 //--------------------------------------------------------------------// 971 972 /** 973 * Construct a class from its constituent loaded parts 974 * 975 * @param typeRef the type reference that was resolved to this class 976 * @param constantPool array of ints encoding constant value 977 * @param modifiers {@link org.jikesrvm.classloader.ClassLoaderConstants} 978 * @param superClass parent of this class 979 * @param declaredInterfaces array of interfaces this class implements 980 * @param declaredFields fields of the class 981 * @param declaredMethods methods of the class 982 * @param declaredClasses declared inner classes 983 * @param enclosingClass the class that this class is declared in (for inner classes) 984 * @param enclosingMethod the method that this class is declared in (for anonymous classes) 985 * @param declaringClass outer class if an inner class 986 * @param sourceName source file name 987 * @param classInitializerMethod handle to class initializer method 988 * @param signature the generic type name for this class 989 * @param annotations array of runtime visible annotations 990 */ 991 RVMClass(TypeReference typeRef, int[] constantPool, short modifiers, RVMClass superClass, 992 RVMClass[] declaredInterfaces, RVMField[] declaredFields, RVMMethod[] declaredMethods, 993 TypeReference[] declaredClasses, TypeReference declaringClass, TypeReference enclosingClass, 994 MethodReference enclosingMethod, Atom sourceName, RVMMethod classInitializerMethod, 995 Atom signature, RVMAnnotation[] annotations) { 996 super(typeRef, 0, annotations); 997 if (VM.VerifyAssertions) VM._assert(!getTypeRef().isUnboxedType()); 998 if (VM.VerifyAssertions && null != superClass) VM._assert(!superClass.getTypeRef().isUnboxedType()); 999 1000 // final fields 1001 this.constantPool = constantPool; 1002 this.modifiers = modifiers; 1003 this.superClass = superClass; 1004 this.declaredInterfaces = declaredInterfaces; 1005 this.declaredFields = declaredFields; 1006 this.declaredMethods = declaredMethods; 1007 this.declaredClasses = declaredClasses; 1008 this.declaringClass = declaringClass; 1009 this.enclosingClass = enclosingClass; 1010 this.enclosingMethod = enclosingMethod; 1011 this.sourceName = sourceName; 1012 this.classInitializerMethod = classInitializerMethod; 1013 this.signature = signature; 1014 1015 // non-final fields 1016 this.subClasses = emptyVMClass; 1017 state = CLASS_LOADED; 1018 1019 // we're about to leak a reference to 'this' force memory to be 1020 // consistent 1021 Magic.sync(); 1022 1023 if (superClass != null) { 1024 // MUST wait until end of constructor to 'publish' the subclass link. 1025 // If we do this earlier, then people can see an incomplete RVMClass object 1026 // by traversing the subclasses of our superclass! 1027 superClass.addSubClass(this); 1028 } 1029 1030 this.desiredAssertionStatus = RVMClassLoader.getDesiredAssertionStatus(this); 1031 1032 Callbacks.notifyClassLoaded(this); 1033 1034 if (VM.TraceClassLoading && VM.runningVM) { 1035 VM.sysWriteln("RVMClass: (end) load file " + typeRef.getName()); 1036 } 1037 if (VM.verboseClassLoading) VM.sysWrite("[Loaded " + toString() + "]\n"); 1038 } 1039 1040 /** 1041 * {@inheritDoc} Space in the JTOC is allocated for static fields, 1042 * static methods and constructors. Moreover, this method generates size 1043 * and offset information for members of this class.<p> 1044 * 1045 * Side effects: superclasses and superinterfaces are resolved. 1046 */ 1047 @Override 1048 public synchronized void resolve() { 1049 if (isResolved()) return; 1050 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) resolve " + this); 1051 if (VM.VerifyAssertions) VM._assert(state == CLASS_LOADED); 1052 1053 // Resolve superclass and super interfaces 1054 // 1055 if (superClass != null) { 1056 superClass.resolve(); 1057 } 1058 for (RVMClass declaredInterface : declaredInterfaces) { 1059 declaredInterface.resolve(); 1060 } 1061 1062 if (isInterface()) { 1063 if (VM.VerifyAssertions) VM._assert(superClass == null); 1064 depth = 1; 1065 thinLockOffset = Offset.max(); 1066 } else if (superClass == null) { 1067 if (VM.VerifyAssertions) VM._assert(isJavaLangObjectType()); 1068 instanceSize = ObjectModel.computeScalarHeaderSize(this); 1069 alignment = BYTES_IN_ADDRESS; 1070 thinLockOffset = ObjectModel.defaultThinLockOffset(); 1071 depth = 0; 1072 } else { 1073 depth = superClass.depth + 1; 1074 thinLockOffset = superClass.thinLockOffset; 1075 instanceSize = superClass.instanceSize; 1076 fieldLayoutContext = superClass.fieldLayoutContext; 1077 alignment = superClass.alignment; 1078 } 1079 1080 if (this == RVMType.JavaLangClassType) { 1081 ObjectModel.allocateThinLock(this); 1082 } 1083 1084 if (superClass != null && superClass.isNonMoving() && !isNonMoving()) { 1085 VM.sysWriteln("WARNING: movable " + this + " extends non-moving " + superClass); 1086 } 1087 1088 if (VM.verboseClassLoading) VM.sysWrite("[Preparing " + this + "]\n"); 1089 1090 // build field and method lists for this class 1091 // 1092 { 1093 FieldVector staticFields = new FieldVector(); 1094 FieldVector instanceFields = new FieldVector(); 1095 MethodVector staticMethods = new MethodVector(); 1096 MethodVector constructorMethods = new MethodVector(); 1097 MethodVector virtualMethods = new MethodVector(); 1098 1099 // start with fields and methods of superclass 1100 // 1101 if (superClass != null) { 1102 for (RVMField field : superClass.getInstanceFields()) { 1103 instanceFields.addElement(field); 1104 } 1105 1106 for (RVMMethod method : superClass.getVirtualMethods()) { 1107 virtualMethods.addElement(method); 1108 } 1109 } 1110 1111 // append fields defined by this class 1112 // 1113 for (RVMField field : getDeclaredFields()) { 1114 if (field.isStatic()) { 1115 staticFields.addElement(field); 1116 } else { 1117 instanceFields.addElement(field); 1118 } 1119 } 1120 1121 // append/overlay methods defined by this class 1122 // 1123 for (RVMMethod method : getDeclaredMethods()) { 1124 if (VM.VerifyUnint) { 1125 if (method.isSynchronized() && method.isUninterruptible()) { 1126 if (VM.ParanoidVerifyUnint || !method.hasLogicallyUninterruptibleAnnotation()) { 1127 VM.sysWriteln("WARNING: " + method + " cannot be both uninterruptible and synchronized"); 1128 } 1129 } 1130 } 1131 1132 if (method.isObjectInitializer()) { 1133 Callbacks.notifyMethodOverride(method, null); 1134 constructorMethods.addElement(method); 1135 } else if (method.isStatic()) { 1136 if (!method.isClassInitializer()) { 1137 Callbacks.notifyMethodOverride(method, null); 1138 staticMethods.addElement(method); 1139 } 1140 } else { // Virtual method 1141 1142 if (method.isSynchronized()) { 1143 ObjectModel.allocateThinLock(this); 1144 } 1145 1146 // method could override something in superclass - check for it 1147 // 1148 int superclassMethodIndex = -1; 1149 for (int j = 0, m = virtualMethods.size(); j < m; ++j) { 1150 RVMMethod alreadyDefinedMethod = virtualMethods.elementAt(j); 1151 if (alreadyDefinedMethod.getName() == method.getName() && 1152 alreadyDefinedMethod.getDescriptor() == method.getDescriptor()) { 1153 // method already defined in superclass 1154 superclassMethodIndex = j; 1155 break; 1156 } 1157 } 1158 1159 if (superclassMethodIndex == -1) { 1160 Callbacks.notifyMethodOverride(method, null); 1161 virtualMethods.addElement(method); // append 1162 } else { 1163 RVMMethod superc = virtualMethods.elementAt(superclassMethodIndex); 1164 if (VM.VerifyUnint) { 1165 if (!superc.isInterruptible() && method.isInterruptible()) { 1166 VM.sysWriteln("WARNING: interruptible " + method + " overrides uninterruptible " + superc); 1167 } 1168 } 1169 Callbacks.notifyMethodOverride(method, superc); 1170 virtualMethods.setElementAt(method, superclassMethodIndex); // override 1171 } 1172 } 1173 } 1174 1175 // Deal with Miranda methods. 1176 // If this is an abstract class, then for each 1177 // interface that this class implements, ensure that a corresponding virtual 1178 // method is declared. If one is not, then create an abstract method to fill the void. 1179 if (!isInterface() && isAbstract()) { 1180 for (RVMClass I : declaredInterfaces) { 1181 RVMMethod[] iMeths = I.getVirtualMethods(); 1182 outer: 1183 for (RVMMethod iMeth : iMeths) { 1184 Atom iName = iMeth.getName(); 1185 Atom iDesc = iMeth.getDescriptor(); 1186 for (int k = 0; k < virtualMethods.size(); k++) { 1187 RVMMethod vMeth = virtualMethods.elementAt(k); 1188 if (vMeth.getName() == iName && vMeth.getDescriptor() == iDesc) continue outer; 1189 } 1190 MemberReference mRef = MemberReference.findOrCreate(typeRef, iName, iDesc); 1191 virtualMethods.addElement(new AbstractMethod(getTypeRef(), 1192 mRef, 1193 (short) (ACC_ABSTRACT | ACC_PUBLIC), 1194 iMeth.getExceptionTypes(), 1195 null, 1196 null, 1197 null, 1198 null)); 1199 } 1200 } 1201 } 1202 1203 // If this is an interface, inherit methods from its superinterfaces 1204 if (isInterface()) { 1205 for (RVMClass declaredInterface : declaredInterfaces) { 1206 RVMMethod[] meths = declaredInterface.getVirtualMethods(); 1207 for (RVMMethod meth : meths) { 1208 virtualMethods.addUniqueElement(meth); 1209 } 1210 } 1211 } 1212 1213 this.staticFields = staticFields.finish(); 1214 this.instanceFields = instanceFields.finish(); 1215 this.staticMethods = staticMethods.finish(); 1216 this.constructorMethods = constructorMethods.finish(); 1217 this.virtualMethods = virtualMethods.finish(); 1218 } 1219 1220 // allocate space for class fields 1221 // 1222 for (RVMField field : staticFields) { 1223 if (field.isReferenceType()) { 1224 field.setOffset(Statics.allocateReferenceSlot(true)); 1225 } else if (field.getSize() <= BYTES_IN_INT) { 1226 field.setOffset(Statics.allocateNumericSlot(BYTES_IN_INT, true)); 1227 } else { 1228 field.setOffset(Statics.allocateNumericSlot(BYTES_IN_LONG, true)); 1229 } 1230 1231 // (SJF): Serialization nastily accesses even final private static 1232 // fields via pseudo-reflection! So, we must shove the 1233 // values of final static fields into the JTOC. Now 1234 // seems to be a good time. 1235 if (field.isFinal()) { 1236 setFinalStaticJTOCEntry(field, field.getOffset()); 1237 } 1238 } 1239 1240 // lay out instance fields 1241 // 1242 ObjectModel.layoutInstanceFields(this); 1243 1244 // count reference fields 1245 int referenceFieldCount = 0; 1246 for (RVMField field : instanceFields) { 1247 if (field.isTraced()) { 1248 referenceFieldCount += 1; 1249 } 1250 } 1251 1252 // record offsets of those instance fields that contain references 1253 // 1254 if (typeRef.isRuntimeTable()) { 1255 referenceOffsets = MemoryManager.newNonMovingIntArray(0); 1256 } else { 1257 referenceOffsets = MemoryManager.newNonMovingIntArray(referenceFieldCount); 1258 int j = 0; 1259 for (RVMField field : instanceFields) { 1260 if (field.isTraced()) { 1261 referenceOffsets[j++] = field.getOffset().toInt(); 1262 } 1263 } 1264 } 1265 1266 // Allocate space for <init> method pointers 1267 // 1268 for (RVMMethod method : constructorMethods) { 1269 method.setOffset(Statics.allocateReferenceSlot(true)); 1270 } 1271 1272 // Allocate space for static method pointers 1273 // 1274 for (RVMMethod method : staticMethods) { 1275 if (method.isClassInitializer()) { 1276 method.setOffset(Offset.fromIntZeroExtend(0xebad0ff5)); // should never be used. 1277 } else { 1278 method.setOffset(Statics.allocateReferenceSlot(true)); 1279 } 1280 } 1281 1282 if (!isInterface()) { 1283 // lay out virtual method section of type information block 1284 // (to be filled in by instantiate) 1285 for (int i = 0, n = virtualMethods.length; i < n; ++i) { 1286 RVMMethod method = virtualMethods[i]; 1287 method.setOffset(TIB.getVirtualMethodOffset(i)); 1288 } 1289 } 1290 1291 // RCGC: Determine if class is inherently acyclic 1292 acyclic = false; // must initially be false for recursive types 1293 boolean foundCyclic = false; 1294 for (RVMField instanceField : instanceFields) { 1295 TypeReference ft = instanceField.getType(); 1296 if (!ft.isResolved() || !ft.peekType().isAcyclicReference()) { 1297 foundCyclic = true; 1298 break; 1299 } 1300 } 1301 if (!foundCyclic) { 1302 acyclic = true; 1303 } 1304 1305 // allocate "type information block" 1306 TIB allocatedTib; 1307 if (isInterface()) { 1308 allocatedTib = MemoryManager.newTIB(0, AlignmentEncoding.ALIGN_CODE_NONE); 1309 } else if (isAnnotationDeclared(TypeReference.ReferenceFieldsVary)) { 1310 allocatedTib = MemoryManager.newTIB(virtualMethods.length, HandInlinedScanning.fallback()); 1311 } else { 1312 allocatedTib = MemoryManager.newTIB(virtualMethods.length, HandInlinedScanning.scalar(referenceOffsets)); 1313 } 1314 1315 superclassIds = DynamicTypeCheck.buildSuperclassIds(this); 1316 doesImplement = DynamicTypeCheck.buildDoesImplement(this); 1317 1318 // can't move this beyond "finalize" code block as findVirtualMethod 1319 // assumes state >= RESOLVED, no allocation occurs until 1320 // state >= CLASS_INITIALIZING 1321 publishResolved(allocatedTib, superclassIds, doesImplement); 1322 1323 // TODO: Make this into a more general listener interface 1324 if (VM.BuildForOptCompiler && VM.writingBootImage) { 1325 classLoadListener.classInitialized(this, true); 1326 } 1327 1328 Callbacks.notifyClassResolved(this); 1329 MemoryManager.notifyClassResolved(this); 1330 1331 // check for a "finalize" method that overrides the one in java.lang.Object 1332 // 1333 if (!isInterface()) { 1334 final RVMMethod method = 1335 findVirtualMethod(RVMClassLoader.StandardObjectFinalizerMethodName, 1336 RVMClassLoader.StandardObjectFinalizerMethodDescriptor); 1337 if (!method.getDeclaringClass().isJavaLangObjectType()) { 1338 hasFinalizer = true; 1339 } 1340 } 1341 1342 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end) resolve " + this); 1343 } 1344 1345 /** 1346 * Atomically initialize the important parts of the TIB and let the world know this type is 1347 * resolved. 1348 * 1349 * @param allocatedTib The TIB that has been allocated for this type 1350 * @param superclassIds The calculated superclass ids array 1351 * @param doesImplement The calculated does implement array 1352 */ 1353 @Uninterruptible 1354 private void publishResolved(TIB allocatedTib, short[] superclassIds, int[] doesImplement) { 1355 Statics.setSlotContents(getTibOffset(), allocatedTib); 1356 allocatedTib.setType(this); 1357 allocatedTib.setSuperclassIds(superclassIds); 1358 allocatedTib.setDoesImplement(doesImplement); 1359 typeInformationBlock = allocatedTib; 1360 state = CLASS_RESOLVED; 1361 } 1362 1363 @Override 1364 public void allBootImageTypesResolved() { 1365 for (RVMMethod method : declaredMethods) { 1366 if (method instanceof NormalMethod) { 1367 ((NormalMethod)method).recomputeSummary(constantPool); 1368 } 1369 } 1370 } 1371 1372 1373 /** 1374 * @return <code>true</code> if the class is acyclic and 1375 * final (otherwise the reference could be to a subsequently loaded 1376 * cyclic subclass) 1377 */ 1378 @Override 1379 @Uninterruptible 1380 public boolean isAcyclicReference() { 1381 return acyclic && isFinal(); 1382 } 1383 1384 /** 1385 * Inserts the value of a final static field into the JTOC. 1386 * 1387 * @param field the field whose value we want to insert 1388 * @param fieldOffset the field's offset in the JTOC 1389 */ 1390 private void setFinalStaticJTOCEntry(RVMField field, Offset fieldOffset) { 1391 if (!field.isFinal()) return; 1392 1393 // value Index: index into the classes constant pool. 1394 int valueIndex = field.getConstantValueIndex(); 1395 1396 // if there's no value in the constant pool, bail out 1397 if (valueIndex <= 0) return; 1398 1399 Offset literalOffset = field.getDeclaringClass().getLiteralOffset(valueIndex); 1400 1401 if (Statics.isReference(Statics.offsetAsSlot(fieldOffset))) { 1402 Object obj = Statics.getSlotContentsAsObject(literalOffset); 1403 Statics.setSlotContents(fieldOffset, obj); 1404 } else if (field.getSize() <= BYTES_IN_INT) { 1405 // copy one word from constant pool to JTOC 1406 int value = Statics.getSlotContentsAsInt(literalOffset); 1407 Statics.setSlotContents(fieldOffset, value); 1408 } else { 1409 // copy two words from constant pool to JTOC 1410 long value = Statics.getSlotContentsAsLong(literalOffset); 1411 Statics.setSlotContents(fieldOffset, value); 1412 } 1413 } 1414 1415 /** 1416 * {@inheritDoc} The TIB will also be built.<p> 1417 * 1418 * Side effects: superclasses are instantiated. 1419 */ 1420 @Override 1421 public synchronized void instantiate() { 1422 if (isInstantiated()) { 1423 return; 1424 } 1425 1426 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) instantiate " + this); 1427 if (VM.VerifyAssertions) VM._assert(state == CLASS_RESOLVED); 1428 1429 // instantiate superclass 1430 // 1431 if (superClass != null) { 1432 superClass.instantiate(); 1433 } 1434 if (VM.runningVM) { 1435 // can't instantiate if building bootimage, since this can cause 1436 // class initializer to be lost (when interface is not included in bootimage). 1437 // since we don't need to instantiate/initialize for the purposes of 1438 // dynamic type checking and interface invocation, defer it until runtime 1439 // and the class actually refers to a static field of the interface. 1440 for (RVMClass declaredInterface : declaredInterfaces) { 1441 declaredInterface.instantiate(); 1442 } 1443 } 1444 1445 if (!isInterface()) { 1446 // Create the internal lazy method invoker trampoline 1447 typeInformationBlock.initializeInternalLazyCompilationTrampoline(); 1448 1449 // Initialize slots in the TIB for virtual methods 1450 for (int i = 0; i < virtualMethods.length; i++) { 1451 RVMMethod method = virtualMethods[i]; 1452 if (method.isPrivate() && method.getDeclaringClass() != this) { 1453 typeInformationBlock.setVirtualMethod(i, null); // an inherited private method....will never be invoked via this TIB 1454 } else { 1455 typeInformationBlock.setVirtualMethod(i, method.getCurrentEntryCodeArray()); 1456 } 1457 } 1458 1459 // compile <init> methods and put their addresses into jtoc 1460 for (RVMMethod method : constructorMethods) { 1461 Statics.setSlotContents(method.getOffset(), method.getCurrentEntryCodeArray()); 1462 } 1463 1464 // compile static methods and put their addresses into jtoc 1465 for (RVMMethod method : staticMethods) { 1466 // don't bother compiling <clinit> here; 1467 // compile it right before we invoke it in initialize. 1468 // This also avoids putting <clinit>s in the bootimage. 1469 if (!method.isClassInitializer()) { 1470 Statics.setSlotContents(method.getOffset(), method.getCurrentEntryCodeArray()); 1471 } 1472 } 1473 } 1474 1475 InterfaceInvocation.initializeDispatchStructures(this); 1476 SpecializedMethodManager.notifyTypeInstantiated(this); 1477 1478 if (VM.writingBootImage) { 1479 state = CLASS_INITIALIZED; 1480 // Mark final fields as literals as class initializer won't have been called 1481 markFinalFieldsAsLiterals(); 1482 } else { 1483 state = CLASS_INSTANTIATED; 1484 } 1485 1486 Callbacks.notifyClassInstantiated(this); 1487 if (VM.writingBootImage) { 1488 Callbacks.notifyClassInitialized(this); 1489 } 1490 1491 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end) instantiate " + this); 1492 } 1493 1494 /** 1495 * Make the passed field a traced field by garbage collection. Also affects all 1496 * subclasses. 1497 * 1498 * @param field the field that we want to make traced 1499 */ 1500 public void makeFieldTraced(RVMField field) { 1501 int[] oldOffsets = referenceOffsets; 1502 int fieldOffset = field.getOffset().toInt(); 1503 referenceOffsets = MemoryManager.newNonMovingIntArray(oldOffsets.length + 1); 1504 int i; 1505 for (i = 0; i < oldOffsets.length && oldOffsets[i] < fieldOffset; i++) { 1506 referenceOffsets[i] = oldOffsets[i]; 1507 } 1508 referenceOffsets[i++] = fieldOffset; 1509 while (i < referenceOffsets.length) { 1510 referenceOffsets[i] = oldOffsets[i - 1]; 1511 i++; 1512 } 1513 SpecializedMethodManager.refreshSpecializedMethods(this); 1514 1515 for (RVMClass klass: subClasses) { 1516 klass.makeFieldTraced(field); 1517 } 1518 } 1519 1520 /** 1521 * {@inheritDoc}<p> 1522 * 1523 * Side effects: superclasses are initialized, static fields receive 1524 * initial values. 1525 */ 1526 @Override 1527 public synchronized void initialize() throws ExceptionInInitializerError { 1528 if (isInitialized()) { 1529 return; 1530 } 1531 1532 if (state == CLASS_INITIALIZING) { 1533 return; 1534 } 1535 1536 if (state == CLASS_INITIALIZER_FAILED) { 1537 throw new NoClassDefFoundError(this + " (initialization failure)"); 1538 } 1539 1540 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) initialize " + this); 1541 if (VM.VerifyAssertions) VM._assert(state == CLASS_INSTANTIATED); 1542 state = CLASS_INITIALIZING; 1543 if (VM.verboseClassLoading) VM.sysWrite("[Initializing " + this + "]\n"); 1544 1545 // run super <clinit> 1546 // 1547 if (superClass != null) { 1548 superClass.initialize(); 1549 } 1550 1551 // run <clinit> 1552 // 1553 if (classInitializerMethod != null) { 1554 CompiledMethod cm = classInitializerMethod.getCurrentCompiledMethod(); 1555 while (cm == null) { 1556 classInitializerMethod.compile(); 1557 cm = classInitializerMethod.getCurrentCompiledMethod(); 1558 } 1559 1560 if (VM.verboseClassLoading) VM.sysWrite("[Running static initializer for " + this + "]\n"); 1561 1562 try { 1563 Magic.invokeClassInitializer(cm.getEntryCodeArray()); 1564 } catch (Error e) { 1565 state = CLASS_INITIALIZER_FAILED; 1566 throw e; 1567 } catch (Throwable t) { 1568 ExceptionInInitializerError eieio = new ExceptionInInitializerError("While initializing " + this); 1569 eieio.initCause(t); 1570 state = CLASS_INITIALIZER_FAILED; 1571 if (VM.verboseClassLoading) { 1572 VM.sysWriteln("[Exception in initializer error caused by:"); 1573 t.printStackTrace(); 1574 VM.sysWriteln("]"); 1575 } 1576 throw eieio; 1577 } 1578 1579 // <clinit> is no longer needed: reclaim space by removing references to it 1580 classInitializerMethod.invalidateCompiledMethod(cm); 1581 classInitializerMethod = null; 1582 } 1583 1584 if (VM.BuildForOptCompiler) { 1585 // report that a class is about to be marked initialized to 1586 // the opt compiler so it can invalidate speculative CHA optimizations 1587 // before an instance of this class could actually be created. 1588 classLoadListener.classInitialized(this, false); 1589 } 1590 1591 state = CLASS_INITIALIZED; 1592 1593 Callbacks.notifyClassInitialized(this); 1594 1595 markFinalFieldsAsLiterals(); 1596 1597 if (VM.verboseClassLoading) VM.sysWrite("[Initialized " + this + "]\n"); 1598 if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end) initialize " + this); 1599 } 1600 1601 /** 1602 * Mark final fields as being available as literals 1603 */ 1604 private void markFinalFieldsAsLiterals() { 1605 for (RVMField f : getStaticFields()) { 1606 if (f.isFinal()) { 1607 Offset fieldOffset = f.getOffset(); 1608 if (Statics.isReference(Statics.offsetAsSlot(fieldOffset))) { 1609 Statics.markAsReferenceLiteral(fieldOffset); 1610 } else { 1611 Statics.markAsNumericLiteral(f.getSize(), fieldOffset); 1612 } 1613 } 1614 } 1615 } 1616 1617 /** 1618 * Copy the values of all static final fields into 1619 * the JTOC. Note: This method should only be run AFTER 1620 * the class initializer has run. 1621 */ 1622 public void setAllFinalStaticJTOCEntries() { 1623 if (VM.VerifyAssertions) VM._assert(isInitialized()); 1624 for (RVMField f : getStaticFields()) { 1625 if (f.isFinal()) { 1626 setFinalStaticJTOCEntry(f, f.getOffset()); 1627 } 1628 } 1629 } 1630 1631 void resolveNativeMethods() { 1632 if (VM.VerifyAssertions) VM._assert(isInitialized()); 1633 resolveNativeMethodsInternal(getStaticMethods()); 1634 resolveNativeMethodsInternal(getVirtualMethods()); 1635 } 1636 1637 private void resolveNativeMethodsInternal(RVMMethod[] methods) { 1638 for (RVMMethod m : methods) { 1639 if (m.isNative()) { 1640 m.replaceCompiledMethod(null); 1641 } 1642 } 1643 } 1644 1645 /** 1646 * Unregisters all native methods declared by "this". 1647 */ 1648 public void unregisterNativeMethods() { 1649 if (VM.VerifyAssertions) VM._assert(isInitialized()); 1650 for (RVMMethod m : declaredMethods) { 1651 if (m.isNative()) { 1652 NativeMethod nm = (NativeMethod) m; 1653 nm.unregisterNativeSymbol(); 1654 m.replaceCompiledMethod(null); 1655 } 1656 } 1657 } 1658 1659 private synchronized void addSubClass(RVMClass sub) { 1660 int n = subClasses.length; 1661 RVMClass[] tmp = new RVMClass[n + 1]; 1662 System.arraycopy(subClasses, 0, tmp, 0, n); 1663 tmp[n] = sub; 1664 subClasses = tmp; 1665 } 1666 1667 //------------------------------------------------------------// 1668 // Support for speculative optimizations that may need to 1669 // invalidate compiled code when new classes are loaded. 1670 // 1671 // TODO: Make this into a more general listener API 1672 //------------------------------------------------------------// 1673 public static final ClassLoadingListener classLoadListener = 1674 VM.BuildForOptCompiler ? new ClassLoadingDependencyManager() : null; 1675 1676 /** 1677 * Given a method declared by this class, update all 1678 * dispatching tables to refer to the current compiled 1679 * code for the method. 1680 * 1681 * @param m the method whose tables need to be updated 1682 */ 1683 public void updateMethod(RVMMethod m) { 1684 if (VM.VerifyAssertions) VM._assert(isResolved()); 1685 if (VM.VerifyAssertions) VM._assert(m.getDeclaringClass() == this); 1686 if (m.isClassInitializer()) return; // we never put this method in the jtoc anyways! 1687 1688 if (m.isStatic() || m.isObjectInitializer()) { 1689 updateJTOCEntry(m); 1690 } else { 1691 updateVirtualMethod(m); 1692 // If this is a java.lang.Object method, also update all the TIBs 1693 // for array types (since arrays can call this method) 1694 if (m.getDeclaringClass().isJavaLangObjectType()) { 1695 RVMType.updateArrayMethods(m); 1696 } 1697 } 1698 } 1699 1700 /** 1701 * Updates the JTOC slot for the given static method to point to 1702 * the current compiled code for the given method. 1703 * NOTE: This method is intentionally not synchronized to avoid deadlocks. 1704 * We instead rely on the fact that we are always updating the JTOC with 1705 * the most recent instructions for the method. 1706 * 1707 * @param m the method whose JTOC entry will be updated 1708 */ 1709 public void updateJTOCEntry(RVMMethod m) { 1710 if (VM.VerifyAssertions) VM._assert(m.getDeclaringClass() == this); 1711 if (VM.VerifyAssertions) VM._assert(isResolved()); 1712 if (VM.VerifyAssertions) VM._assert(m.isStatic() || m.isObjectInitializer()); 1713 Statics.setSlotContents(m.getOffset(), m.getCurrentEntryCodeArray()); 1714 } 1715 1716 /** 1717 * Updates this class's TIB entry for the given method to point to 1718 * the current compiled code for the given method.<p> 1719 * NOTE: This method is intentionally not synchronized to avoid deadlocks. 1720 * We instead rely on the fact that we are always updating the JTOC with 1721 * the most recent instructions for the method. 1722 * 1723 * @param m the method whose class' TIB entry will be updated 1724 */ 1725 public void updateTIBEntry(RVMMethod m) { 1726 if (VM.VerifyAssertions) { 1727 RVMMethod vm = findVirtualMethod(m.getName(), m.getDescriptor()); 1728 VM._assert(vm == m); 1729 } 1730 typeInformationBlock.setVirtualMethod(m.getOffset(), m.getCurrentEntryCodeArray()); 1731 InterfaceInvocation.updateTIBEntry(this, m); 1732 } 1733 1734 /** 1735 * Update the TIB entry's for all classes that inherit the given method 1736 * to point to the current compiled code for the given method.<p> 1737 * NOTE: This method is intentionally not synchronized to avoid deadlocks. 1738 * We instead rely on the fact that we are always updating the JTOC with 1739 * the most recent instructions for the method. 1740 * 1741 * @param m the method 1742 */ 1743 public void updateVirtualMethod(RVMMethod m) { 1744 RVMMethod dm = findDeclaredMethod(m.getName(), m.getDescriptor()); 1745 if (dm != null && dm != m) return; // this method got overridden 1746 updateTIBEntry(m); 1747 if (m.isPrivate()) return; // can't override 1748 for (RVMClass sc : getSubClasses()) { 1749 if (sc.isResolved()) { 1750 sc.updateVirtualMethod(m); 1751 } 1752 } 1753 } 1754 1755 //------------------------------------------------------------// 1756 // Additional fields and methods for Interfaces // 1757 //------------------------------------------------------------// 1758 1759 private static final Object interfaceCountLock = new Object(); 1760 private static int interfaceCount = 0; 1761 private static RVMClass[] interfaces; 1762 private int interfaceId = -1; 1763 RVMMethod[] noIMTConflictMap; // used by InterfaceInvocation to support resetTIB 1764 1765 /** 1766 * Classes used as Interfaces get assigned an interface id. 1767 * If the class is not an interface, attempting to use this 1768 * id will cause an IncompatibleClassChangeError to be thrown 1769 * 1770 * @return interface id (a non-negative number) 1771 */ 1772 public int getInterfaceId() { 1773 if (interfaceId == -1) { 1774 assignInterfaceId(); 1775 } 1776 return interfaceId; 1777 } 1778 1779 public int getDoesImplementIndex() { 1780 return getInterfaceId() >>> 5; 1781 } 1782 1783 public int getDoesImplementBitMask() { 1784 return 1 << (getInterfaceId() & 31); 1785 } 1786 1787 public static RVMClass getInterface(int id) { 1788 return interfaces[id]; 1789 } 1790 1791 private synchronized void assignInterfaceId() { 1792 if (interfaceId == -1) { 1793 if (interfaceCountLock != null && interfaces != null) { 1794 synchronized (interfaceCountLock) { 1795 interfaceId = interfaceCount++; 1796 if (interfaceId == interfaces.length) { 1797 RVMClass[] tmp = new RVMClass[interfaces.length * 2]; 1798 System.arraycopy(interfaces, 0, tmp, 0, interfaces.length); 1799 interfaces = tmp; 1800 } 1801 interfaces[interfaceId] = this; 1802 } 1803 } else { 1804 interfaceId = interfaceCount++; 1805 if (interfaces == null) { 1806 interfaces = new RVMClass[200]; 1807 } 1808 interfaces[interfaceId] = this; 1809 } 1810 } 1811 } 1812 1813 /** 1814 * Number of [ in descriptor for arrays; -1 for primitives; 0 for 1815 * classes 1816 * @return 0 1817 */ 1818 @Override 1819 @Pure 1820 @Uninterruptible 1821 public int getDimensionality() { 1822 return 0; 1823 } 1824 1825 @Override 1826 @Uninterruptible 1827 public boolean isResolved() { 1828 return state >= CLASS_RESOLVED; 1829 } 1830 1831 @Override 1832 @Uninterruptible 1833 public boolean isInstantiated() { 1834 return state >= CLASS_INSTANTIATED; 1835 } 1836 1837 @Override 1838 @Uninterruptible 1839 public boolean isInitialized() { 1840 return state == CLASS_INITIALIZED; 1841 } 1842 1843 @Override 1844 public void markAsBootImageClass() { 1845 inBootImage = true; 1846 } 1847 1848 @Override 1849 @Uninterruptible 1850 public boolean isInBootImage() { 1851 return inBootImage; 1852 } 1853 1854 /** 1855 * @return the offset in instances of this type assigned to the thin lock word. 1856 * Is only known after class has been resolved. 1857 */ 1858 @Override 1859 @Uninterruptible 1860 public Offset getThinLockOffset() { 1861 if (VM.VerifyAssertions) VM._assert(isResolved()); 1862 return thinLockOffset; 1863 } 1864 1865 /** 1866 * Sets the thin lock offset for instances of this type. Can be called at most once. 1867 * and is invoked from ObjectModel.allocateThinLock (in object models which 1868 * do not allocate thin locks for all scalar object types). 1869 * 1870 * @param offset the offset for the thin lock 1871 */ 1872 public void setThinLockOffset(Offset offset) { 1873 if (VM.VerifyAssertions) VM._assert(thinLockOffset.isMax()); 1874 if (VM.VerifyAssertions) VM._assert(!offset.isMax()); 1875 thinLockOffset = offset; 1876 } 1877 1878 /** 1879 * @return number of superclasses to Object 1880 */ 1881 @Override 1882 @Pure 1883 @Uninterruptible 1884 public int getTypeDepth() { 1885 return depth; 1886 } 1887 1888 /** 1889 * @return <code>true</code> 1890 */ 1891 @Override 1892 @Pure 1893 @Uninterruptible 1894 public boolean isClassType() { 1895 return true; 1896 } 1897 1898 /** 1899 * @return <code>false</code> 1900 */ 1901 @Override 1902 @Pure 1903 @Uninterruptible 1904 public boolean isArrayType() { 1905 return false; 1906 } 1907 1908 /** 1909 * @return <code>false</code> 1910 */ 1911 @Override 1912 @Pure 1913 @Uninterruptible 1914 public boolean isPrimitiveType() { 1915 return false; 1916 } 1917 1918 /** 1919 * @return <code>true</code> 1920 */ 1921 @Override 1922 @Pure 1923 @Uninterruptible 1924 public boolean isReferenceType() { 1925 return true; 1926 } 1927 1928 /** 1929 * @return <code>false</code> 1930 */ 1931 @Override 1932 @Pure 1933 @Uninterruptible 1934 public boolean isUnboxedType() { 1935 return false; 1936 } 1937 1938 public static boolean isClassLoadingDisabled() { 1939 return classLoadingDisabled; 1940 } 1941 1942 /** 1943 * Provides a way to disable and re-enable classloading for testing purposes. 1944 * <p> 1945 * Note: General clients must not call this method. 1946 * 1947 * @param classLoadingDisabled {@code true} if classloading is to be disabled, 1948 * {@code false} if it is to be enabled 1949 */ 1950 public static void setClassLoadingDisabled(boolean classLoadingDisabled) { 1951 RVMClass.classLoadingDisabled = classLoadingDisabled; 1952 } 1953 1954 /** 1955 * Create a synthetic class that extends ReflectionBase and invokes the given method 1956 * @param methodToCall the method we wish to call reflectively 1957 * @return the synthetic class 1958 */ 1959 static Class<?> createReflectionClass(RVMMethod methodToCall) { 1960 if (VM.VerifyAssertions) VM._assert(VM.runningVM); 1961 if (DynamicTypeCheck.instanceOfResolved(TypeReference.baseReflectionClass.resolve(), methodToCall.getDeclaringClass())) { 1962 // Avoid reflection on reflection base class 1963 return null; 1964 } 1965 int[] constantPool = new int[methodToCall.getParameterTypes().length + 3]; 1966 String reflectionClassName = "Lorg/jikesrvm/classloader/ReflectionBase$$Reflect" + 1967 methodToCall.getMemberRef().getId() + ";"; 1968 TypeReference reflectionClass = TypeReference.findOrCreate(reflectionClassName); 1969 RVMType klass = reflectionClass.peekType(); 1970 if (klass == null) { 1971 MethodReference reflectionMethodRef = MethodReference.findOrCreate(reflectionClass, 1972 Atom.findOrCreateUnicodeAtom("invokeInternal"), 1973 Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;") 1974 ).asMethodReference(); 1975 MethodReference constructorMethodRef = MethodReference.findOrCreate(reflectionClass, 1976 Atom.findOrCreateUnicodeAtom("<init>"), 1977 Atom.findOrCreateUnicodeAtom("()V") 1978 ).asMethodReference(); 1979 1980 RVMMethod[] reflectionMethods = new RVMMethod[]{ 1981 methodToCall.createReflectionMethod(reflectionClass, constantPool, reflectionMethodRef), 1982 RVMMethod.createDefaultConstructor(reflectionClass, constructorMethodRef)}; 1983 klass = 1984 new RVMClass(reflectionClass, constantPool, (short) (ACC_SYNTHETIC | ACC_PUBLIC | ACC_FINAL), // modifiers 1985 TypeReference.baseReflectionClass.resolve().asClass(), // superClass 1986 emptyVMClass, // declaredInterfaces 1987 emptyVMField, reflectionMethods, 1988 null, null, null, null, null, null, null, null); 1989 reflectionClass.setType(klass); 1990 RuntimeEntrypoints.initializeClassForDynamicLink(klass.asClass()); 1991 } 1992 return klass.getClassForType(); 1993 } 1994}