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       * Reference Count GC: Is a reference of this type contained in
175       * another object inherently acyclic (without cycles) ?
176       * @return true
177       */
178      @Override
179      @Pure
180      @Uninterruptible
181      public boolean isAcyclicReference() {
182        return true;
183      }
184    
185      /**
186       * Number of [ in descriptor for arrays; -1 for primitives; 0 for
187       * classes
188       * @return -1;
189       */
190      @Override
191      @Pure
192      @Uninterruptible
193      public int getDimensionality() {
194        return -1;
195      }
196    
197      /**
198       * Resolution status.
199       * @return true
200       */
201      @Override
202      @Uninterruptible
203      public boolean isResolved() {
204        return true;
205      }
206    
207      /**
208       * Instantiation status.
209       * @return true
210       */
211      @Override
212      @Pure
213      @Uninterruptible
214      public boolean isInstantiated() {
215        return true;
216      }
217    
218      /**
219       * Initialization status.
220       * @return true
221       */
222      @Override
223      @Pure
224      @Uninterruptible
225      public boolean isInitialized() {
226        return true;
227      }
228    
229      /**
230       * Only intended to be used by the BootImageWriter
231       */
232      @Override
233      public void markAsBootImageClass() {}
234    
235      /**
236       * Is this class part of the virtual machine's boot image?
237       */
238      @Override
239      @Pure
240      @Uninterruptible
241      public boolean isInBootImage() {
242        return true;
243      }
244    
245      /**
246       * Get the offset in instances of this type assigned to the thin
247       * lock word.  Offset.max() if instances of this type do not have thin lock
248       * words.
249       * @return Offset.max();
250       */
251      @Override
252      @Pure
253      @Uninterruptible
254      public Offset getThinLockOffset() {
255        if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
256        return Offset.max();
257      }
258    
259      /**
260       * Whether or not this is an instance of RVMClass?
261       * @return false
262       */
263      @Override
264      @Pure
265      @Uninterruptible
266      public boolean isClassType() {
267        return false;
268      }
269    
270      /**
271       * Whether or not this is an instance of RVMArray?
272       * @return false
273       */
274      @Override
275      @Pure
276      @Uninterruptible
277      public boolean isArrayType() {
278        return false;
279      }
280    
281      /**
282       * Whether or not this is a primitive type
283       * @return true
284       */
285      @Override
286      @Pure
287      @Uninterruptible
288      public boolean isPrimitiveType() {
289        return true;
290      }
291    
292      /**
293       * @return whether or not this is a reference (ie non-primitive) type.
294       */
295      @Override
296      @Pure
297      @Uninterruptible
298      public boolean isReferenceType() {
299        return false;
300      }
301    
302      /**
303       * @return whether or not this is an unboxed type
304       */
305      @Override
306      @Pure
307      @Uninterruptible
308      public boolean isUnboxedType() {
309        return false;
310      }
311    
312      /**
313       * Stack space requirement in words.
314       */
315      @Override
316      @Pure
317      @Uninterruptible
318      public int getStackWords() {
319        return stackWords;
320      }
321    
322      /**
323       * Space required in memory in bytes.
324       */
325      @Override
326      @Pure
327      @Uninterruptible
328      public int getMemoryBytes() {
329        return memoryBytes;
330      }
331    
332      /**
333       * Cause resolution to take place.
334       */
335      @Override
336      @Pure
337      public void resolve() {}
338    
339      @Override
340      public void allBootImageTypesResolved() { }
341    
342      /**
343       * Cause instantiation to take place.
344       */
345      @Override
346      @Pure
347      public void instantiate() {}
348    
349      /**
350       * Cause initialization to take place.
351       */
352      @Override
353      @Pure
354      public void initialize() {}
355    
356      /**
357       * Does this type override java.lang.Object.finalize()?
358       */
359      @Override
360      @Pure
361      @Uninterruptible
362      public boolean hasFinalizer() {
363        return false;
364      }
365    
366      /*
367       * Primitives are not first class objects -
368       * but the implementation of reflection is cleaner if
369       * we pretend that they are and provide dummy implementations of
370       * the following methods
371       */
372    
373      /**
374       * Static fields of this class/array type.
375       * @return zero length array
376       */
377      @Override
378      @Pure
379      public RVMField[] getStaticFields() {
380        return emptyVMField;
381      }
382    
383      /**
384       * Non-static fields of this class/array type
385       * (composed with supertypes, if any).
386       * @return zero length array
387       */
388      @Override
389      @Pure
390      public RVMField[] getInstanceFields() {
391        return emptyVMField;
392      }
393    
394      /**
395       * Statically dispatched methods of this class/array type.
396       * @return zero length array
397       */
398      @Override
399      @Pure
400      public RVMMethod[] getStaticMethods() {
401        return emptyVMMethod;
402      }
403    
404      /**
405       * Virtually dispatched methods of this class/array type
406       * (composed with supertypes, if any).
407       * @return zero length array
408       */
409      @Override
410      @Pure
411      public RVMMethod[] getVirtualMethods() {
412        return emptyVMMethod;
413      }
414    
415      /**
416       * Runtime type information for this class/array type.
417       */
418      @Override
419      @Uninterruptible
420      public TIB getTypeInformationBlock() {
421        if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
422        return null;
423      }
424    }