001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.classloader;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.Constants;
017    import org.vmmagic.pragma.Uninterruptible;
018    import org.vmmagic.unboxed.Offset;
019    
020    /**
021     * A field or method of a java class.
022     */
023    public abstract class RVMMember extends AnnotatedElement implements Constants, ClassLoaderConstants {
024    
025      /** Initial value for a field offset - indicates field not laid out. */
026      private static final int NO_OFFSET = Short.MIN_VALUE + 1;
027    
028      /**
029       * The class that declared this member, available by calling
030       * getDeclaringClass once the class is loaded.
031       */
032      private final TypeReference declaringClass;
033    
034      /**
035       * The canonical MemberReference for this member
036       */
037      protected final MemberReference memRef;
038    
039      /**
040       * The modifiers associated with this member.
041       */
042      protected final short modifiers;
043    
044      /**
045       * The signature is a string representing the generic type for this
046       * field or method declaration, may be null
047       */
048      private final Atom signature;
049    
050      /**
051       * The member's jtoc/obj/tib offset in bytes.
052       * Set by {@link RVMClass#resolve()}
053       */
054      protected int offset;
055    
056      /**
057       * NOTE: Only {@link RVMClass} is allowed to create an instance of a RVMMember.
058       *
059       * @param declaringClass the TypeReference object of the class that declared this member
060       * @param memRef the canonical memberReference for this member.
061       * @param modifiers modifiers associated with this member.
062       * @param signature generic type of this member
063       * @param annotations array of runtime visible annotations
064       */
065      protected RVMMember(TypeReference declaringClass, MemberReference memRef, short modifiers, Atom signature,
066                          RVMAnnotation[] annotations) {
067        super(annotations);
068        this.declaringClass = declaringClass;
069        this.memRef = memRef;
070        this.modifiers = modifiers;
071        this.signature = signature;
072        this.offset = NO_OFFSET; // invalid value. Set to valid value during RVMClass.resolve()
073      }
074    
075      //--------------------------------------------------------------------//
076      //                         Section 1.                                 //
077      // The following are available after class loading.                   //
078      //--------------------------------------------------------------------//
079    
080      /**
081       * Class that declared this field or method. Not available before
082       * the class is loaded.
083       */
084      @Uninterruptible
085      public final RVMClass getDeclaringClass() {
086        return declaringClass.peekType().asClass();
087      }
088    
089      /**
090       * Canonical member reference for this member.
091       */
092      @Uninterruptible
093      public final MemberReference getMemberRef() {
094        return memRef;
095      }
096    
097      /**
098       * Name of this member.
099       */
100      @Uninterruptible
101      public final Atom getName() {
102        return memRef.getName();
103      }
104    
105      /**
106       * Descriptor for this member.
107       * something like "I" for a field or "(I)V" for a method.
108       */
109      @Uninterruptible
110      public final Atom getDescriptor() {
111        return memRef.getDescriptor();
112      }
113    
114      /**
115       * Generic type for member
116       */
117      public final Atom getSignature() {
118        return signature;
119      }
120    
121      /**
122       * Get a unique id for this member.
123       * The id is the id of the canonical MemberReference for this member
124       * and thus may be used to find the member by first finding the member reference.
125       */
126      @Uninterruptible
127      public final int getId() {
128        return memRef.getId();
129      }
130    
131      /*
132       * Define hashcode in terms of Atom.hashCode to enable
133       * consistent hash codes during bootImage writing and run-time.
134       */
135      @Override
136      public int hashCode() {
137        return memRef.hashCode();
138      }
139    
140      @Override
141      public final String toString() {
142        return declaringClass + "." + getName() + " " + getDescriptor();
143      }
144    
145      /**
146       * Usable from classes outside its package?
147       */
148      public final boolean isPublic() {
149        return (modifiers & ACC_PUBLIC) != 0;
150      }
151    
152      /**
153       * Usable only from this class?
154       */
155      public final boolean isPrivate() {
156        return (modifiers & ACC_PRIVATE) != 0;
157      }
158    
159      /**
160       * Usable from subclasses?
161       */
162      public final boolean isProtected() {
163        return (modifiers & ACC_PROTECTED) != 0;
164      }
165    
166      /**
167       * Get the member's modifiers.
168       */
169      public final int getModifiers() {
170        return modifiers;
171      }
172    
173      /**
174       * Has the field been laid out in the object yet ?
175       *
176       * @return {@code true} if the field has been assigned an offset, {@code false} if not
177       */
178      public final boolean hasOffset() {
179        return !(offset == NO_OFFSET);
180      }
181    
182      //------------------------------------------------------------------//
183      //                       Section 2.                                 //
184      // The following are available after the declaring class has been   //
185      // "resolved".                                                      //
186      //------------------------------------------------------------------//
187    
188      /**
189       * Offset of this field or method, in bytes.
190       * <ul>
191       * <li> For a static field:      offset of field from start of jtoc
192       * <li> For a static method:     offset of code object reference from start of jtoc
193       * <li> For a non-static field:  offset of field from start of object
194       * <li> For a non-static method: offset of code object reference from start of tib
195       * </ul>
196       */
197      @Uninterruptible
198      public final Offset getOffset() {
199        if (VM.VerifyAssertions) VM._assert(declaringClass!=null);
200        if (VM.VerifyAssertions) VM._assert(declaringClass.isLoaded());
201        if (VM.VerifyAssertions) VM._assert(offset != NO_OFFSET);
202        return Offset.fromIntSignExtend(offset);
203      }
204    
205      /**
206       * Only meant to be used by ObjectModel.layoutInstanceFields.
207       * TODO: refactor system so this functionality is in the classloader package
208       * and this method doesn't have to be final.
209       */
210      public final void setOffset(Offset off) {
211        offset = off.toInt();
212      }
213    }
214