1 // Copyright (c) 1997, 2000, 2003, 2004, 2006, 2009  Per M.A. Bothner.
2 // This is free software;  for terms and warranty disclaimer see ./COPYING.
3 
4 package gnu.bytecode;
5 import java.util.*;
6 import gnu.kawa.util.AbstractWeakHashTable;
7 
8 /** An abstract type as used by both gnu.bytecode and gnu.expr. */
9 
10 public abstract class Type
11 /* #ifdef JAVA5 */
12  implements java.lang.reflect.Type
13 /* #endif */
14 {
15   String signature;
16   String genericSignature;
17   // Fully-qualified name (in external format, i.e. using '.' to separate).
18   String this_name;
19   /**
20    * Nominal unpromoted size in bytes.
21    */
22   int size;
23 
24   ArrayType array_type;
25 
Type()26   protected Type () { }
27 
28   /** Return Java-level implementation type.
29    * The type used to implement types not natively understood by the JVM
30    * or the Java language.
31    * Usually, the identity function.  However, a language might handle
32    * union types or template types or type expressions calculated at
33    * run time.  In that case return the type used at the Java level,
34    * and known at compile time.
35    */
getImplementationType()36   public Type getImplementationType()
37   {
38     return this;
39   }
40 
41     /** Return JVM-level implementation type. */
getRawType()42     public Type getRawType() {
43 	Type t = getImplementationType();
44 	if (t != this && t != null)
45 	    t = t.getRawType();
46 	return t;
47     }
48 
49     /** If this is a type alias, get the aliased type.
50      * This is semi-deprecated.
51      */
getRealType()52     public Type getRealType() {
53 	return this;
54     }
55 
isInterface()56     public boolean isInterface() {
57         Type raw = getRawType();
58         return raw != this && raw.isInterface();
59     }
60 
isExisting()61   public boolean isExisting()
62   {
63     // Overridden in ObjectType.
64     return true;
65   }
66 
67   static ClassToTypeMap mapClassToType;
68 
69   /** Maps Java type name (e.g. "java.lang.String[]") to corresponding Type. */
70   /* #ifdef JAVA5 */
71   static java.util.HashMap<String,Type> mapNameToType;
72   /* #else */
73   // static java.util.Hashtable mapNameToType;
74   /* #endif */
75 
lookupType(String name)76   public static Type lookupType (String name)
77   {
78     /* #ifdef JAVA5 */
79     java.util.HashMap<String,Type> map = mapNameToType;
80     synchronized (map) { return map.get(name); }
81     /* #else */
82     // return (Type) mapNameToType.get(name);
83     /* #endif */
84   }
85 
86   /** Find an Type with the given name, or create a new one.
87    * Use this for "library classes", where you need the field/method types,
88    * but not one where you are about to generate code for.
89    * @param name the name of the class (e..g. "java.lang.String").
90    */
getType(String name)91   public static Type getType (String name)
92   {
93     /* #ifdef JAVA5 */
94     java.util.HashMap<String,Type> map = mapNameToType;
95     /* #else */
96     // java.util.Hashtable map = mapNameToType;
97     /* #endif */
98     synchronized (map)
99       {
100         Type type = (Type) map.get(name);
101         if (type == null)
102           {
103             if (name.endsWith("[]"))
104               type = ArrayType.make(name);
105             else
106               {
107                 ClassType cl = new ClassType(name);
108                 cl.setExisting(true);
109                 type = cl;
110               }
111             map.put(name, type);
112           }
113         return type;
114       }
115   }
116 
117   /** Register that the Type for class is type. */
registerTypeForClass(Class clas, Type type)118   public synchronized static void registerTypeForClass(Class clas, Type type)
119   {
120     ClassToTypeMap map = mapClassToType;
121     if (map == null)
122       mapClassToType = map = new ClassToTypeMap();
123     type.reflectClass = clas;
124     map.put(clas, type);
125   }
126 
127     /** Try to map java.lang.reflect.Type to gnu.bytecode.Type.
128      * If we can't handle that, resolve the Class instead.
129      */
make(Class reflectClass, java.lang.reflect.Type type)130     public static Type make(Class reflectClass, java.lang.reflect.Type type) {
131 	Type t = make(type);
132 	return t != null ? t : make(reflectClass);
133     }
134 
135     /** Resolve a java.lang.reflect.Type to gnu.bytecode.Type.
136      * Handles simple parameterized types, but does not handle type variables.
137      * @return a translated Type, or null for unhandled types.
138      */
make(java.lang.reflect.Type type)139     static Type make(java.lang.reflect.Type type) {
140 	if (type instanceof Class)
141 	    return make((Class) type);
142 	if (type instanceof java.lang.reflect.GenericArrayType)
143 	    return null;
144 	if (type instanceof java.lang.reflect.ParameterizedType) {
145 	    java.lang.reflect.ParameterizedType ptype
146 		= (java.lang.reflect.ParameterizedType) type;
147 	    java.lang.reflect.Type typeArguments[]
148 		= ptype.getActualTypeArguments();
149 	    Type rt = Type.make(ptype.getRawType());
150 	    if (rt instanceof ClassType) {
151 		ClassType rawType = (ClassType) rt;
152 		int nargs = typeArguments.length;
153 		Type[] typeArgumentTypes = new Type[nargs];
154 		char[] bounds = new char[nargs];
155 		for (int i = 0;  i < nargs;  i++) {
156 		    java.lang.reflect.Type ti = typeArguments[i];
157 		    if (ti instanceof java.lang.reflect.WildcardType) {
158 			java.lang.reflect.WildcardType wi =
159 			    (java.lang.reflect.WildcardType) ti;
160 			java.lang.reflect.Type[] lower = wi.getLowerBounds();
161 			java.lang.reflect.Type[] upper = wi.getUpperBounds();
162 			if (lower.length + upper.length != 1)
163 			    return null;
164 			else if (lower.length == 1) {
165 			    bounds[i] = '-';
166 			    ti = lower[0];
167 			}
168 			else /* if (upper.length == 1) */ {
169 			    bounds[i] = '+';
170 			    ti = upper[0];
171 			}
172 		    }
173 		    typeArgumentTypes[i] = Type.make(ti);
174 		}
175 		ParameterizedType ret = new ParameterizedType(rawType, typeArgumentTypes);
176 		ret.setTypeArgumentBounds(bounds);
177 		return ret;
178 	    }
179 	}
180 	if (type instanceof java.lang.reflect.TypeVariable) {
181 	    return TypeVariable.make((java.lang.reflect.TypeVariable) type);
182 	}
183 	return null;
184     }
185 
make(Class reflectClass)186   public synchronized static Type make(Class reflectClass)
187   {
188     Type type;
189 
190     if (mapClassToType != null)
191       {
192 	Type t = mapClassToType.get(reflectClass);
193 	if (t != null)
194 	  return t;
195       }
196     if (reflectClass.isArray())
197       type = ArrayType.make(Type.make(reflectClass.getComponentType()));
198     else if (reflectClass.isPrimitive())
199       throw new Error("internal error - primitive type not found");
200     else
201       {
202 	String name = reflectClass.getName();
203         /* #ifdef JAVA5 */
204         java.util.HashMap<String,Type> map = mapNameToType;
205         /* #else */
206         // java.util.Hashtable map = mapNameToType;
207         /* #endif */
208         synchronized (map)
209           {
210             type = (Type) map.get(name);
211             if (type == null
212                 || (type.reflectClass != reflectClass
213                     && type.reflectClass != null))
214               {
215                 ClassType cl = new ClassType(name);
216                 cl.setExisting(true);
217                 type = cl;
218                 mapNameToType.put(name, type);
219               }
220           }
221       }
222     registerTypeForClass(reflectClass, type);
223     return type;
224   }
225 
getSignature()226     public String getSignature() { return signature; }
setSignature(String sig)227     protected void setSignature(String sig) { this.signature = sig; }
getGenericSignature()228     public String getGenericSignature() { return genericSignature; }
setGenericSignature(String sig)229     protected void setGenericSignature(String sig) { this.genericSignature = sig; }
getMaybeGenericSignature()230     public String getMaybeGenericSignature() {
231 	String s = getGenericSignature();
232 	return s != null ? s : getSignature();
233     }
234 
Type(String nam, String sig)235   Type (String nam, String sig) {
236     this_name = nam;
237     signature = sig;
238   }
239 
Type(Type type)240   public Type (Type type)
241   {
242     this_name = type.this_name;
243     signature = type.signature;
244     size = type.size;
245     reflectClass = type.reflectClass;
246   }
247 
promote()248   public Type promote () {
249     return size < 4 ? intType : this;
250   }
251 
promoteIfUnsigned()252   public Type promoteIfUnsigned() {
253       if (this instanceof PrimType) {
254           char sig1 = signature.charAt(0);
255           if ((sig1 == 'B' || sig1 == 'S') && ((PrimType) this).isUnsigned())
256               return intType;
257       }
258       return this;
259   }
260 
getSize()261   public final int getSize() { return size; }
getSizeInWords()262   public int getSizeInWords () { return size > 4 ? 2 : 1; }
263 
isVoid()264   public final boolean isVoid () { return size == 0; }
265 
266   /** Returns the primitive type corresponding to a signature character.
267    * @return a primitive type, or null if there is no such type. */
signatureToPrimitive(char sig)268   public static PrimType signatureToPrimitive(char sig)
269   {
270     switch(sig)
271       {
272       case 'B':  return Type.byteType;
273       case 'C':  return Type.charType;
274       case 'D':  return Type.doubleType;
275       case 'F':  return Type.floatType;
276       case 'S':  return Type.shortType;
277       case 'I':  return Type.intType;
278       case 'J':  return Type.longType;
279       case 'Z':  return Type.booleanType;
280       case 'V':  return Type.voidType;
281       }
282     return null;
283   }
284 
285   /** Get a Type corresponding to the given signature string. */
signatureToType(String sig, int off, int len)286   public static Type signatureToType(String sig, int off, int len)
287   {
288     if (len == 0)
289       return null;
290     char c = sig.charAt(off);
291     Type type;
292     if (len == 1)
293       {
294 	type = signatureToPrimitive(c);
295 	if (type != null)
296 	  return type;
297       }
298     if (c == '[')
299       {
300 	type = signatureToType(sig, off+1, len-1);
301 	return type == null ? null : ArrayType.make(type);
302       }
303     if (c == 'L' && len > 2 && sig.indexOf(';', off) == len-1+off)
304       return ClassType.make(sig.substring(off+1,len-1+off).replace('/', '.'));
305     return null;
306   }
307 
308   /** Get a Type corresponding to the given signature string. */
signatureToType(String sig)309   public static Type signatureToType(String sig)
310   {
311     return signatureToType(sig, 0, sig.length());
312   }
313 
printSignature(String sig, int off, int len, java.io.PrintWriter out)314   public static void printSignature (String sig, int off, int len,
315                                      java.io.PrintWriter out)
316   {
317     if (len == 0)
318       return;
319     char c = sig.charAt(off);
320     Type type;
321     if (len == 1)
322       {
323 	type = signatureToPrimitive(c);
324 	if (type != null)
325 	  out.print(type.getName());
326       }
327     else if (c == '[')
328       {
329         printSignature(sig, off+1, len-1, out);
330         out.print("[]");
331       }
332     else if (c == 'L' && len > 2 && sig.indexOf(';', off) == len-1+off)
333       out.print(sig.substring(off+1,len-1+off).replace('/', '.'));
334     else
335       out.append(sig, off, len-off);
336   }
337 
338   /** Return the length of the signature starting at a given string position.
339    * Returns -1 for an invalid signature. */
signatureLength(String sig, int pos)340   public static int signatureLength (String sig, int pos)
341   {
342     int len = sig.length();
343     if (len <= pos)
344       return -1;
345     char c = sig.charAt(pos);
346     int arrays = 0;
347     while (c == '[')
348       {
349 	arrays++;
350 	pos++;
351 	c = sig.charAt(pos);
352       }
353     if (signatureToPrimitive(c) != null)
354       return arrays+1;
355     if (c == 'L')
356       {
357 	int end = sig.indexOf(';', pos);
358 	if (end > 0)
359 	  return arrays + end + 1 - pos;
360       }
361     return -1;
362   }
363 
signatureLength(String sig)364   public static int signatureLength (String sig)
365   {
366     return signatureLength(sig, 0);
367   }
368 
369   /** Returns the Java-level type name from a given signature.
370    * Returns null for an invalid signature. */
signatureToName(String sig)371   public static String signatureToName(String sig)
372   {
373     int len = sig.length();
374     if (len == 0)
375       return null;
376     char c = sig.charAt(0);
377     Type type;
378     if (len == 1)
379       {
380 	type = signatureToPrimitive(c);
381 	if (type != null)
382 	  return type.getName();
383       }
384     if (c == '[')
385       {
386 	int arrays = 1;
387 	if (arrays < len && sig.charAt(arrays) == '[')
388 	  arrays++;
389 	sig = signatureToName(sig.substring(arrays));
390 	if (sig == null)
391 	  return null;
392 	StringBuffer buf = new StringBuffer(50);
393 	buf.append(sig);
394 	while (--arrays >= 0)
395 	  buf.append("[]");
396 	return buf.toString();
397       }
398     if (c == 'L' && len > 2 && sig.indexOf(';') == len-1)
399       return sig.substring(1,len-1).replace('/', '.');
400     return null;
401   }
402 
getName()403   public String getName ()
404   {
405     return this_name;
406   }
407 
setName(String name)408   protected void setName (String name)
409   {
410     this_name = name;
411   }
412 
isValidJavaTypeName(String name)413   public static boolean isValidJavaTypeName (String name)
414   {
415     boolean in_name = false;
416     int i;
417     int len = name.length();
418     while (len > 2 && name.charAt(len-1) == ']'
419 	   && name.charAt(len-2) == '[')
420       len -= 2;
421     for (i = 0;  i < len; i++)
422       {
423 	char ch = name.charAt(i);
424 	if (ch == '.')
425 	  {
426 	    if (in_name)
427 	      in_name = false;
428 	    else
429 	      return false;
430 	  }
431 	else if (in_name ? Character.isJavaIdentifierPart(ch)
432 		 : Character.isJavaIdentifierStart(ch))
433 	  in_name = true;
434 	else
435 	  return false;
436       }
437     return i == len;
438   }
439 
isInstance(Object obj)440   public boolean isInstance (Object obj)
441   {
442     return getReflectClass().isInstance(obj);
443   }
444 
445   /** Return true if this is a "subtype" of other. */
isSubtype(Type other)446   public final boolean isSubtype (Type other)
447   {
448     int comp = compare(other);
449     return comp == -1 || comp == 0;
450   }
451 
452     /** If this is the target type, is a given source type compatible?
453      * @return -1 if not compatible; 0 if need to check at run-time;
454      *   1 if compatible; 2 if compatible and no conversion or cast needed.
455      *   We also return 0 for some "narrowing" conversions even if we know
456      *   they will always succeed, so as to make such conversions less
457      *   preferred when doing method overloading.
458      */
isCompatibleWithValue(Type valueType)459     public int isCompatibleWithValue(Type valueType) {
460         if (Type.isSame(this, valueType))
461             return 2;
462         if (this == toStringType)
463             return valueType == javalangStringType ? 2 : 0;
464         // Hack for LangPrimType.charType.
465         if (this == charType && valueType.getImplementationType()== this)
466             return 2;
467         return isCompatibleWithValue(this, valueType);
468     }
469 
isCompatibleWithValue(Type targetType, Type valueType)470     public static int isCompatibleWithValue(Type targetType, Type valueType) {
471         int comp = targetType.compare(valueType);
472         return comp >= 0 ? 1 : comp == -3 ? -1 : 0;
473     }
474 
475   /**
476    * Computes the common supertype
477    *
478    * Interfaces are not taken into account.
479    * This would be difficult, since interfaces allow multiple-inheritance.
480    * This means that there may exists multiple common supertypes
481    * to t1 and t2 that are not comparable.
482    *
483    * @return the lowest type that is both above t1 and t2,
484    *  or null if t1 and t2 have no common supertype.
485    */
lowestCommonSuperType(Type t1, Type t2)486   public static Type lowestCommonSuperType(Type t1, Type t2)
487   {
488     if (t1 == neverReturnsType)
489       return t2;
490     if (t2 == neverReturnsType)
491       return t1;
492     if (t1 == null || t2 == null)
493       return null;
494     if (t1 == t2)
495       return t1;
496     if (t1 instanceof PrimType && t2 instanceof PrimType)
497       {
498         t1 = ((PrimType) t1).promotedType();
499         t2 = ((PrimType) t2).promotedType();
500         return t1 == t2 ? t1 : null;
501       }
502     return lowestCommonSharedType(t1, t2);
503   }
504 
lowestCommonSharedType(Type t1, Type t2)505   public static Type lowestCommonSharedType(Type t1, Type t2)
506   {
507     if (t1.isSubtype(t2))
508       return t2;
509     else if (t2.isSubtype(t1))
510       return t1;
511     else
512       {
513        // the only chance left is that t1 and t2 are ClassTypes.
514        if (!(t1 instanceof ClassType && t2 instanceof ClassType))
515          return Type.objectType;
516        ClassType c1 = (ClassType) t1;
517        ClassType c2 = (ClassType) t2;
518        if (! c1.isInterface() && ! c2.isInterface())
519          {
520            ClassType s1 = c1.getSuperclass();
521            ClassType s2 = c2.getSuperclass();
522            if (s1 != null && s2 != null)
523              return lowestCommonSuperType(s1, s2);
524          }
525       }
526     return Type.objectType;
527   }
528 
529   /** Return a numeric code showing "subtype" relationship:
530    *  1: if other is a pure subtype of this;
531    *  0: if has the same values;
532    * -1: if this is a pure subtype of other;
533    * -2: if they have values in common but neither is a subtype of the other;
534    * -3: if the types have no values in common.
535    * "Same values" is rather loose;  by "A is a subtype of B"
536    * we mean that all instance of A can be "widened" to B.
537    * More formally, A.compare(B) returns:
538    *  1: all B values can be converted to A without a coercion failure
539    *     (i.e. a ClassCastException or overflow or major loss of information),
540    *     but not vice versa.
541    *  0: all A values can be converted to B without a coercion failure
542    *     and vice versa;
543    * -1: all A values can be converted to B without a coercion failure
544    *     but not vice versa;
545    * -2: there are (potentially) some A values that can be converted to B,
546    *     and some B values can be converted to A;
547    * -3: there are no A values that can be converted to B, and neither
548    *     are there any B values that can be converted to A.
549    */
compare(Type other)550   public abstract int compare(Type other);
551 
552   /** Change result from compare to compensate for argument swapping. */
swappedCompareResult(int code)553   protected static int swappedCompareResult(int code)
554   {
555     return code == 1 ? -1 : code == -1 ? 1 : code;
556   }
557 
558   /** Return true iff t1[i].isSubtype(t2[i]) for all i. */
isMoreSpecific(Type[] t1, Type[] t2)559   public static boolean isMoreSpecific (Type[] t1, Type[] t2)
560   {
561     if (t1.length != t2.length)
562       return false;
563     for (int i = t1.length; --i >= 0; )
564       {
565 	if (! t1[i].isSubtype(t2[i]))
566 	  return false;
567       }
568     return true;
569   }
570 
isSame(Type t1, Type t2)571     public static boolean isSame(Type t1, Type t2) {
572         return t1 == t2
573             || (t1 != null && t2 != null && t1.equals(t2));
574     }
575 
emitIsInstance(CodeAttr code)576   public void emitIsInstance (CodeAttr code)
577   {
578     code.emitInstanceof(this);
579   }
580 
581     /** Convert an object to a value of this Type.
582      * The result is actually of the implementation type, boxed as appropriate,
583      * so it is suitable for standard reflective operations,
584      * like the arguments to Field#set or Method#invoke.
585      * Throw a ClassCastException when this is not possible.
586      */
coerceFromObject(Object obj)587     public abstract Object coerceFromObject (Object obj);
588 
589     /** Given a raw JVM value convert it to an object of this type.
590      * I.e. the argument is an object of the type returned by
591      * {@code getRawType()}, boxed as needed.  The result may be
592      * a language-specific (boxed) value. Generally a no-op.
593      */
coerceToObject(Object obj)594     public Object coerceToObject(Object obj) {
595         return obj;
596     }
597 
598   /** Convert from stackType (usually PrimType) to this type.
599    * However, we might only convert part-way, to some object type.
600    * If converting to this type might fail at run-time, only convert
601    * to Object (as by emitCoerceToObject); a caller can use
602    * {@code stackType.emitConvertFromObject} to convert the rest,
603    * but that might throw an exception. (This is a bit of a kludge.)
604    */
emitConvertFromPrimitive(Type stackType, CodeAttr code)605   public void emitConvertFromPrimitive (Type stackType, CodeAttr code)
606   {
607     stackType.emitCoerceToObject(code);
608   }
609 
610   /** Compile code to convert a object of this type on the stack to Object. */
emitCoerceToObject(CodeAttr code)611   public void emitCoerceToObject (CodeAttr code)
612   {
613   }
614 
615   /** Compile code to coerce/convert from Object to this type. */
emitCoerceFromObject(CodeAttr code)616   public void emitCoerceFromObject (CodeAttr code)
617   {
618     throw new Error ("unimplemented emitCoerceFromObject for "+this);
619   }
620 
621   public static final PrimType byteType
622     = new PrimType ("byte", "B", 1, java.lang.Byte.TYPE);
623   public static final PrimType shortType
624     = new PrimType ("short", "S", 2, java.lang.Short.TYPE);
625   public static final PrimType intType
626     = new PrimType ("int", "I", 4, java.lang.Integer.TYPE);
627   public static final PrimType longType
628     = new PrimType ("long", "J", 8, java.lang.Long.TYPE);
629   public static final PrimType floatType
630     = new PrimType ("float", "F", 4, java.lang.Float.TYPE);
631   public static final PrimType doubleType
632     = new PrimType ("double", "D", 8, java.lang.Double.TYPE);
633   public static final PrimType booleanType
634     = new PrimType ("boolean", "Z", 1, java.lang.Boolean.TYPE);
635   public static final PrimType charType
636     = new PrimType ("char", "C", 2, java.lang.Character.TYPE);
637   public static final PrimType voidType
638     = new PrimType ("void", "V", 0, java.lang.Void.TYPE);
639 
640   /* @deprecated */  public static final PrimType byte_type = byteType;
641   /* @deprecated */  public static final PrimType short_type = shortType;
642   /* @deprecated */  public static final PrimType int_type = intType;
643   /* @deprecated */  public static final PrimType long_type = longType;
644   /* @deprecated */  public static final PrimType float_type = floatType;
645   /* @deprecated */  public static final PrimType double_type = doubleType;
646   /* @deprecated */  public static final PrimType boolean_type = booleanType;
647   /* @deprecated */  public static final PrimType char_type = charType;
648   /* @deprecated */  public static final PrimType void_type = voidType;
649 
650   static
651   {
652     /* #ifdef JAVA5 */
653     mapNameToType = new java.util.HashMap<String,Type>();
654     /* #else */
655     // mapNameToType = new java.util.Hashtable();
656     /* #endif */
657 	mapNameToType.put("byte",    byteType);
658 	mapNameToType.put("short",   shortType);
659 	mapNameToType.put("int",     intType);
660 	mapNameToType.put("long",    longType);
661 	mapNameToType.put("float",   floatType);
662 	mapNameToType.put("double",  doubleType);
663 	mapNameToType.put("boolean", booleanType);
664 	mapNameToType.put("char",    charType);
665 	mapNameToType.put("void",    voidType);
666   }
667 
668     /** The return type of an expression that never returns, such as a throw. */
669     public static final Type neverReturnsType
670         = ClassType.make("gnu.bytecode.Type$NeverReturns");
671 
672   public static final ClassType javalangObjectType
673     = ClassType.make("java.lang.Object");
674   public static final ClassType objectType = javalangObjectType;
675   public static final ClassType javalangBooleanType
676     = ClassType.make("java.lang.Boolean");
677   public static final ClassType javalangCharacterType
678     = ClassType.make("java.lang.Character");
679   public static final ClassType javalangThrowableType
680     = ClassType.make("java.lang.Throwable");
681   public static final ClassType javalangannotationAnnotationType
682     = ClassType.make("java.lang.annotation.Annotation");
683   public static final Type[] typeArray0 = new Type[0];
684   public static final Method toString_method
685     = objectType.getDeclaredMethod("toString", 0);
686   public static final ClassType javalangNumberType
687     = ClassType.make("java.lang.Number");
688   public static final Method clone_method
689     = Method.makeCloneMethod(objectType);
690   public static final Method intValue_method
691     = javalangNumberType.addMethod("intValue", typeArray0,
692 			    intType, Access.PUBLIC);
693   public static final Method longValue_method
694     = javalangNumberType.addMethod("longValue", typeArray0,
695 			    longType, Access.PUBLIC);
696   public static final Method floatValue_method
697     = javalangNumberType.addMethod("floatValue", typeArray0,
698 			    floatType, Access.PUBLIC);
699   public static final Method doubleValue_method
700     = javalangNumberType.addMethod("doubleValue", typeArray0,
701 			    doubleType, Access.PUBLIC);
702   public static final Method booleanValue_method
703     = javalangBooleanType.addMethod("booleanValue", typeArray0,
704 			      booleanType, Access.PUBLIC);
705   public static final ClassType javalangClassType
706     = ClassType.make("java.lang.Class");
707 
708     public static final ClassType javalanginvokeMethodHandleType
709         = ClassType.make("java.lang.invoke.MethodHandle");
710 
711     /** The magic type of null. */
712     public static final ObjectType nullType
713     //= new ObjectType("(type of null)");
714     = new SpecialObjectType("(type of null)", objectType);
715     public static final ObjectType errorType
716         = new SpecialObjectType("<error-type>", javalangObjectType);
717 
718     static public ClassType javalangStringType = ClassType.make("java.lang.String");
719     /* The String type. but coercion is handled by toString. */
720     public static final ObjectType toStringType
721         = new SpecialObjectType("String", javalangStringType);
722 
723   @Deprecated
724   public static final ClassType pointer_type = javalangObjectType;
725   @Deprecated
726   public static final ClassType string_type = javalangStringType;
727   @Deprecated
728   public static final ObjectType tostring_type = toStringType;
729   @Deprecated
730   public static final ClassType java_lang_Class_type = javalangClassType;
731   @Deprecated
732   public static final ClassType boolean_ctype = javalangBooleanType;
733   public static final ClassType throwable_type = javalangThrowableType;
734   @Deprecated
735   public static final ClassType number_type = javalangNumberType;
736 
737   protected Class reflectClass;
738 
739   /** Get the java.lang.Class object for the representation type. */
getReflectClass()740   public java.lang.Class getReflectClass()
741   {
742     return reflectClass;
743   }
744 
setReflectClass(java.lang.Class rclass)745   public void setReflectClass(java.lang.Class rclass)
746   {
747     reflectClass = rclass;
748   }
749 
toString()750   public String toString()
751   {
752     return "Type " + getName();
753   }
754 
hashCode()755   public int hashCode()
756   {
757     String name = toString();
758     return name == null ? 0 : name.hashCode ();
759   }
760 
761     /** A marker class, used for {@code Type.neverReturnsType}. */
762     public static class NeverReturns {
NeverReturns()763         private NeverReturns() { }
764     }
765 
766   static class ClassToTypeMap extends AbstractWeakHashTable<Class,Type>
767   {
getKeyFromValue(Type type)768     protected Class getKeyFromValue (Type type)
769     {
770       return type.reflectClass;
771     }
772 
matches(Class oldValue, Class newValue)773     protected boolean matches (Class oldValue, Class newValue)
774     {
775       // Minor optimization.
776       return oldValue == newValue;
777     }
778   }
779 }
780