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