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.classloader.ClassLoaderConstants.BooleanTypeCode;
017import static org.jikesrvm.classloader.ClassLoaderConstants.ByteTypeCode;
018import static org.jikesrvm.classloader.ClassLoaderConstants.CharTypeCode;
019import static org.jikesrvm.classloader.ClassLoaderConstants.DoubleTypeCode;
020import static org.jikesrvm.classloader.ClassLoaderConstants.FloatTypeCode;
021import static org.jikesrvm.classloader.ClassLoaderConstants.IntTypeCode;
022import static org.jikesrvm.classloader.ClassLoaderConstants.LongTypeCode;
023import static org.jikesrvm.classloader.ClassLoaderConstants.ShortTypeCode;
024import static org.jikesrvm.classloader.ClassLoaderConstants.VoidTypeCode;
025import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BOOLEAN;
026import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BYTE;
027import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_CHAR;
028import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE;
029import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_FLOAT;
030import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT;
031import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_LONG;
032import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_SHORT;
033
034import org.jikesrvm.VM;
035import org.jikesrvm.objectmodel.TIB;
036import org.vmmagic.pragma.NonMoving;
037import org.vmmagic.pragma.Pure;
038import org.vmmagic.pragma.Uninterruptible;
039import org.vmmagic.unboxed.Offset;
040
041/**
042 * Description of a java "primitive" type (int, float, etc.)
043 *
044 * <p> This description is not read from a ".class" file, but rather
045 * is manufactured by the VM before execution begins.
046 *
047 * <p> Note that instances of primitives are not objects:
048 * <ul>
049 * <li> they are never heap allocated in the virtual machine
050 * <li> they have no virtual methods
051 * <li> they appear only in the virtual machine's stack, in its registers,
052 *   or in fields/elements of class/array instances.
053 * </ul>
054 *
055 * @see RVMType
056 * @see RVMClass
057 * @see RVMArray
058 * @see UnboxedType
059 */
060@NonMoving
061public final class Primitive extends RVMType {
062  /**
063   * The pretty (external) name for this primitive.
064   * For example, for a long the name is 'long'
065   * and the descriptor is 'J'
066   */
067  private final Atom name;
068
069  /**
070   * How many slots in the Java Expression Stack does it take
071   * to hold a value of this primitive type?
072   */
073  private final int stackWords;
074
075  /**
076   * How many bytes in memory does it take to hold a value of this
077   * primitive type?
078   */
079  private final int memoryBytes;
080
081  /**
082   * Name - something like "int".
083   */
084  @Override
085  @Pure
086  public String toString() {
087    return name.toString();
088  }
089
090  /**
091   * Constructor
092   * @param tr   The canonical type reference for this primitive
093   * @param classForType The java.lang.Class representation
094   * @param name The name for this primitive
095   * @param stackWords The stack slots used by this primitive
096   * @param memoryBytes The bytes in memory used by this primitive
097   */
098  private Primitive(TypeReference tr, Class<?> classForType, Atom name, int stackWords, int memoryBytes) {
099    super(tr,    // type reference
100          classForType, // j.l.Class representation
101          -1,    // dimensionality
102          null  // runtime visible annotations
103    );
104    this.name = name;
105    this.stackWords = stackWords;
106    this.memoryBytes = memoryBytes;
107    this.depth = 0;
108  }
109
110  /**
111   * Creates an instance of a {@link Primitive}.
112   * @param tr   The canonical type reference for this primitive
113   * @return a newly created instance of {@link Primitive}
114   */
115  static Primitive createPrimitive(TypeReference tr) {
116    Atom name;
117    int stackWords;
118    int memoryBytes;
119    Class<?> classForType;
120    switch (tr.getName().parseForTypeCode()) {
121      case VoidTypeCode:
122        stackWords = 0;
123        memoryBytes = 0;
124        name = Atom.findOrCreateAsciiAtom("void");
125        classForType = Void.TYPE;
126        break;
127      case BooleanTypeCode:
128        stackWords = 1;
129        memoryBytes = BYTES_IN_BOOLEAN;
130        name = Atom.findOrCreateAsciiAtom("boolean");
131        classForType = Boolean.TYPE;
132        break;
133      case ByteTypeCode:
134        stackWords = 1;
135        memoryBytes = BYTES_IN_BYTE;
136        name = Atom.findOrCreateAsciiAtom("byte");
137        classForType = Byte.TYPE;
138        break;
139      case CharTypeCode:
140        stackWords = 1;
141        memoryBytes = BYTES_IN_CHAR;
142        name = Atom.findOrCreateAsciiAtom("char");
143        classForType = Character.TYPE;
144        break;
145      case ShortTypeCode:
146        stackWords = 1;
147        memoryBytes = BYTES_IN_SHORT;
148        name = Atom.findOrCreateAsciiAtom("short");
149        classForType = Short.TYPE;
150        break;
151      case IntTypeCode:
152        stackWords = 1;
153        memoryBytes = BYTES_IN_INT;
154        name = Atom.findOrCreateAsciiAtom("int");
155        classForType = Integer.TYPE;
156        break;
157      case LongTypeCode:
158        stackWords = 2;
159        memoryBytes = BYTES_IN_LONG;
160        name = Atom.findOrCreateAsciiAtom("long");
161        classForType = Long.TYPE;
162        break;
163      case FloatTypeCode:
164        stackWords = 1;
165        memoryBytes = BYTES_IN_FLOAT;
166        name = Atom.findOrCreateAsciiAtom("float");
167        classForType = Float.TYPE;
168        break;
169      case DoubleTypeCode:
170        stackWords = 2;
171        memoryBytes = BYTES_IN_DOUBLE;
172        name = Atom.findOrCreateAsciiAtom("double");
173        classForType = Double.TYPE;
174        break;
175      default:
176        throw new Error("Unknown primitive " + tr.getName().classFileNameFromDescriptor());
177    }
178    return new Primitive(tr, classForType, name, stackWords, memoryBytes);
179  }
180
181  /**
182   * get number of superclasses to Object
183   * @return 0
184   */
185  @Override
186  @Pure
187  @Uninterruptible
188  public int getTypeDepth() {
189    return 0;
190  }
191
192  /**
193   * @return <code>true</code>
194   */
195  @Override
196  @Pure
197  @Uninterruptible
198  public boolean isAcyclicReference() {
199    return true;
200  }
201
202  /**
203   * Number of [ in descriptor for arrays; -1 for primitives; 0 for
204   * classes
205   * @return -1;
206   */
207  @Override
208  @Pure
209  @Uninterruptible
210  public int getDimensionality() {
211    return -1;
212  }
213
214  /**
215   * @return <code>true</code> because primitives are always considered
216   * "resolved"
217   */
218  @Override
219  @Uninterruptible
220  public boolean isResolved() {
221    return true;
222  }
223
224  /**
225   * @return <code>true</code> because primitives are always considered
226   * "instantiated"
227   */
228  @Override
229  @Pure
230  @Uninterruptible
231  public boolean isInstantiated() {
232    return true;
233  }
234
235  /**
236   * @return <code>true</code> because primitives are always considered
237   * "initialized"
238   */
239  @Override
240  @Pure
241  @Uninterruptible
242  public boolean isInitialized() {
243    return true;
244  }
245
246  @Override
247  public void markAsBootImageClass() {}
248
249  /**
250   * @return <code>true</code> because primitives are needed to start
251   * Jikes RVM
252   */
253  @Override
254  @Pure
255  @Uninterruptible
256  public boolean isInBootImage() {
257    return true;
258  }
259
260  /**
261   * @return Offset.max();
262   */
263  @Override
264  @Pure
265  @Uninterruptible
266  public Offset getThinLockOffset() {
267    if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
268    return Offset.max();
269  }
270
271  /**
272   * @return <code>false</code>
273   */
274  @Override
275  @Pure
276  @Uninterruptible
277  public boolean isClassType() {
278    return false;
279  }
280
281  /**
282   * @return <code>false</code>
283   */
284  @Override
285  @Pure
286  @Uninterruptible
287  public boolean isArrayType() {
288    return false;
289  }
290
291  /**
292   * @return <code>true</code>
293   */
294  @Override
295  @Pure
296  @Uninterruptible
297  public boolean isPrimitiveType() {
298    return true;
299  }
300
301  /**
302   * @return <code>false</code>
303   */
304  @Override
305  @Pure
306  @Uninterruptible
307  public boolean isReferenceType() {
308    return false;
309  }
310
311  /**
312   * @return <code>false</code>
313   */
314  @Override
315  @Pure
316  @Uninterruptible
317  public boolean isUnboxedType() {
318    return false;
319  }
320
321  /**
322   * Stack space requirement in words.
323   */
324  @Override
325  @Pure
326  @Uninterruptible
327  public int getStackWords() {
328    return stackWords;
329  }
330
331  @Override
332  @Pure
333  @Uninterruptible
334  public int getMemoryBytes() {
335    return memoryBytes;
336  }
337
338  /**
339   * Cause resolution to take place. This is a no-op for primitive types.
340   * @see Primitive#isResolved()
341   */
342  @Override
343  @Pure
344  public void resolve() {}
345
346  @Override
347  public void allBootImageTypesResolved() { }
348
349  /**
350   * Cause instantiation to take place. This is a no-op for primitive types.
351   * @see Primitive#isInstantiated()
352   */
353  @Override
354  @Pure
355  public void instantiate() {}
356
357  /**
358   * Cause initialization to take place. This is a no-op for primitive types.
359   * @see Primitive#isInitialized()
360   */
361  @Override
362  @Pure
363  public void initialize() {}
364
365  /**
366   * @return <code>false</code>
367   */
368  @Override
369  @Pure
370  @Uninterruptible
371  public boolean hasFinalizer() {
372    return false;
373  }
374
375  /*
376   * Primitives are not first class objects -
377   * but the implementation of reflection is cleaner if
378   * we pretend that they are and provide dummy implementations of
379   * the following methods
380   */
381
382  /**
383   * Static fields of this class/array type.
384   * @return zero length array
385   */
386  @Override
387  @Pure
388  public RVMField[] getStaticFields() {
389    return emptyVMField;
390  }
391
392  /**
393   * Non-static fields of this class/array type
394   * (composed with supertypes, if any).
395   * @return zero length array
396   */
397  @Override
398  @Pure
399  public RVMField[] getInstanceFields() {
400    return emptyVMField;
401  }
402
403  /**
404   * Statically dispatched methods of this class/array type.
405   * @return zero length array
406   */
407  @Override
408  @Pure
409  public RVMMethod[] getStaticMethods() {
410    return emptyVMMethod;
411  }
412
413  /**
414   * Virtually dispatched methods of this class/array type
415   * (composed with supertypes, if any).
416   * @return zero length array
417   */
418  @Override
419  @Pure
420  public RVMMethod[] getVirtualMethods() {
421    return emptyVMMethod;
422  }
423
424  /**
425   * Runtime type information for this class/array type.
426   */
427  @Override
428  @Uninterruptible
429  public TIB getTypeInformationBlock() {
430    if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
431    return null;
432  }
433}