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