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 }