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