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.VM.NOT_REACHED;
016import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BYTE;
017import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT;
018import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
019
020import org.jikesrvm.VM;
021import org.jikesrvm.objectmodel.TIB;
022import org.vmmagic.pragma.NonMoving;
023import org.vmmagic.pragma.Pure;
024import org.vmmagic.pragma.Uninterruptible;
025import org.vmmagic.unboxed.Offset;
026
027/**
028 * Description of an Unboxed Magic type.<p>
029 *
030 * Currently, unboxed types are restricted to be values that can fit in a single machines word.
031 *
032 * @see RVMType
033 * @see RVMClass
034 * @see RVMArray
035 * @see Primitive
036 */
037@NonMoving
038public final class UnboxedType extends RVMType {
039  /**
040   * The pretty (external) name for this Unboxed type.
041   */
042  private final Atom name;
043
044  /**
045   * How many slots in the Java Expression Stack does it take
046   * to hold a value of this primitive type?
047   */
048  private final int stackWords;
049
050  /**
051   * How many bytes in memory does it take to hold a value of this
052   * primitive type?
053   */
054  private final int memoryBytes;
055
056  /**
057   * Name - something like "int".
058   */
059  @Override
060  @Pure
061  public String toString() {
062    return name.toString();
063  }
064
065  /**
066   * Constructor
067   * @param tr   The canonical type reference for this primitive
068   * @param classForType The java.lang.Class representation
069   * @param name The name for this primitive
070   * @param stackWords The stack slots used by this primitive
071   * @param memoryBytes The bytes in memory used by this primitive
072   */
073  private UnboxedType(TypeReference tr, Class<?> classForType, Atom name, int stackWords, int memoryBytes) {
074    super(tr,    // type reference
075          classForType, // j.l.Class representation
076          -1,    // dimensionality
077          null  // runtime visible annotations
078    );
079    this.name = name;
080    this.stackWords = stackWords;
081    this.memoryBytes = memoryBytes;
082    this.depth = 0;
083  }
084
085  /**
086   * Create an instance of a {@link UnboxedType}
087   * @param tr   The canonical type reference for this primitive
088   *
089   * @return the newly created unboxed type for the type reference
090   */
091  static UnboxedType createUnboxedType(TypeReference tr) {
092    Atom name;
093    int stackWords = 1;
094    int memoryBytes;
095    Class<?> classForType;
096
097    name = tr.getName();
098    if (tr == TypeReference.Address ||
099        tr == TypeReference.Word ||
100        tr == TypeReference.Offset ||
101        tr == TypeReference.Extent) {
102      memoryBytes = BYTES_IN_ADDRESS;
103    } else if (tr == TypeReference.Code) {
104      memoryBytes = VM.BuildForIA32 ? BYTES_IN_BYTE : BYTES_IN_INT;
105    } else {
106      throw new Error("Unknown unboxed type " + tr.getName());
107    }
108    try {
109      classForType = Class.forName(name.classNameFromDescriptor());
110    } catch (Exception e) {
111      throw new Error("Error getting java.lang.Class wrapper for type " + name.classNameFromDescriptor(), e);
112    }
113
114    return new UnboxedType(tr, classForType, name, stackWords, memoryBytes);
115  }
116
117  /**
118   * @return 0 because unboxed types do not extend java.lang.Object
119   */
120  @Override
121  @Pure
122  @Uninterruptible
123  public int getTypeDepth() {
124    return 0;
125  }
126
127  /**
128   * @return <code>true</code> because unboxed types cannot contain any references
129   */
130  @Override
131  @Pure
132  @Uninterruptible
133  public boolean isAcyclicReference() {
134    return true;
135  }
136
137  /**
138   * @return -1
139   */
140  @Override
141  @Pure
142  @Uninterruptible
143  public int getDimensionality() {
144    return -1;
145  }
146
147  /**
148   * @return <code>true</code> because unboxed types are always considered
149   * resolved"
150   */
151  @Override
152  @Uninterruptible
153  public boolean isResolved() {
154    return true;
155  }
156
157  /**
158   * @return <code>true</code> because unboxed types are always considered
159   * "instantiated"
160   */
161  @Override
162  @Pure
163  @Uninterruptible
164  public boolean isInstantiated() {
165    return true;
166  }
167
168  /**
169   * @return <code>true</code> because unboxed types are always considered
170   * "initialized"
171   */
172  @Override
173  @Pure
174  @Uninterruptible
175  public boolean isInitialized() {
176    return true;
177  }
178
179  @Override
180  public void markAsBootImageClass() {}
181
182  /**
183   * @return <code>true</code>. All unboxed types are included in the bootimage
184   * because they are needed for starting Jikes RVM.
185   */
186  @Override
187  @Pure
188  @Uninterruptible
189  public boolean isInBootImage() {
190    return true;
191  }
192
193  /**
194   * @return <code>Offset.max()</code>
195   */
196  @Override
197  @Pure
198  @Uninterruptible
199  public Offset getThinLockOffset() {
200    if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
201    return Offset.max();
202  }
203
204  /**
205   * @return <code>false</code>
206   */
207  @Override
208  @Pure
209  @Uninterruptible
210  public boolean isClassType() {
211    return false;
212  }
213
214  /**
215   * @return <code>false</code>
216   */
217  @Override
218  @Pure
219  @Uninterruptible
220  public boolean isArrayType() {
221    return false;
222  }
223
224  /**
225   * @return <code>false</code>
226   */
227  @Override
228  @Pure
229  @Uninterruptible
230  public boolean isPrimitiveType() {
231    return false;
232  }
233
234  /**
235   * @return <code>false</code>
236   */
237  @Override
238  @Pure
239  @Uninterruptible
240  public boolean isReferenceType() {
241    return false;
242  }
243
244  /**
245   * @return <code>true</code>
246   */
247  @Override
248  @Pure
249  @Uninterruptible
250  public boolean isUnboxedType() {
251    return true;
252  }
253
254  /**
255   * Stack space requirement in words.
256   */
257  @Override
258  @Pure
259  @Uninterruptible
260  public int getStackWords() {
261    return stackWords;
262  }
263
264  @Override
265  @Pure
266  @Uninterruptible
267  public int getMemoryBytes() {
268    return memoryBytes;
269  }
270
271  /**
272   * Cause resolution to take place. This is a no-op for unboxed types.
273   * @see UnboxedType#isResolved()
274   */
275  @Override
276  @Pure
277  public void resolve() {}
278
279  @Override
280  public void allBootImageTypesResolved() { }
281
282  /**
283   * Cause instantiation to take place. This is a no-op for unboxed types.
284   * @see UnboxedType#isInstantiated()
285   */
286  @Override
287  @Pure
288  public void instantiate() {}
289
290  /**
291   * Cause initialization to take place. This is a no-op for unboxed types.
292   * @see UnboxedType#isInitialized()
293   */
294  @Override
295  @Pure
296  public void initialize() {}
297
298  /**
299   * @return false
300   */
301  @Override
302  @Pure
303  @Uninterruptible
304  public boolean hasFinalizer() {
305    return false;
306  }
307
308  /*
309   * Primitives are not first class objects -
310   * but the implementation of reflection is cleaner if
311   * we pretend that they are and provide dummy implementations of
312   * the following methods
313   */
314
315  /**
316   * Static fields of this class/array type.
317   * @return zero length array
318   */
319  @Override
320  @Pure
321  public RVMField[] getStaticFields() {
322    return emptyVMField;
323  }
324
325  /**
326   * Non-static fields of this class/array type
327   * (composed with supertypes, if any).
328   * @return zero length array
329   */
330  @Override
331  @Pure
332  public RVMField[] getInstanceFields() {
333    return emptyVMField;
334  }
335
336  /**
337   * Statically dispatched methods of this class/array type.
338   * @return zero length array
339   */
340  @Override
341  @Pure
342  public RVMMethod[] getStaticMethods() {
343    return emptyVMMethod;
344  }
345
346  /**
347   * Virtually dispatched methods of this class/array type
348   * (composed with supertypes, if any).
349   * @return zero length array
350   */
351  @Override
352  @Pure
353  public RVMMethod[] getVirtualMethods() {
354    return emptyVMMethod;
355  }
356
357  /**
358   * Runtime type information for this class/array type.
359   */
360  @Override
361  @Uninterruptible
362  public TIB getTypeInformationBlock() {
363    if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
364    return null;
365  }
366}