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