001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1997-2000 Etienne Gagnon. All rights reserved.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: package soot.jimple.toolkits.typing;
027:
028: import soot.*;
029: import soot.options.Options;
030:
031: import java.util.*;
032:
033: /**
034: * This class encapsulates the typing class hierarchy, as well as non-reference types.
035: *
036: * <P> This class is primarily used by the TypeResolver class, to optimize its computation.
037: **/
038: public class ClassHierarchy {
039: /** Map: Scene -> ClassHierarchy **/
040:
041: public final TypeNode OBJECT;
042: public final TypeNode CLONEABLE;
043: public final TypeNode SERIALIZABLE;
044: public final TypeNode NULL;
045: public final TypeNode INT;
046: //public final TypeNode UNKNOWN;
047: //public final TypeNode ERROR;
048:
049: /** All type node instances **/
050: private final List<TypeNode> typeNodeList = new ArrayList<TypeNode>();
051:
052: /** Map: Type -> TypeNode **/
053: private final HashMap<Type, TypeNode> typeNodeMap = new HashMap<Type, TypeNode>();
054:
055: /** Used to transform boolean, byte, short and char to int **/
056: private final ToInt transform = new ToInt();
057:
058: /** Used to create TypeNode instances **/
059: private final ConstructorChooser make = new ConstructorChooser();
060:
061: private ClassHierarchy(Scene scene) {
062: if (scene == null) {
063: throw new InternalTypingException();
064: }
065:
066: G.v().ClassHierarchy_classHierarchyMap.put(scene, this );
067:
068: NULL = typeNode(NullType.v());
069: OBJECT = typeNode(RefType.v("java.lang.Object"));
070:
071: // hack for J2ME library which does not have Cloneable and Serializable
072: // reported by Stephen Chen
073: if (!Options.v().j2me()) {
074: CLONEABLE = typeNode(RefType.v("java.lang.Cloneable"));
075: SERIALIZABLE = typeNode(RefType.v("java.io.Serializable"));
076: } else {
077: CLONEABLE = null;
078: SERIALIZABLE = null;
079: }
080:
081: INT = typeNode(IntType.v());
082: }
083:
084: /** Get the class hierarchy for the given scene. **/
085: public static ClassHierarchy classHierarchy(Scene scene) {
086: if (scene == null) {
087: throw new InternalTypingException();
088: }
089:
090: ClassHierarchy classHierarchy = G.v().ClassHierarchy_classHierarchyMap
091: .get(scene);
092:
093: if (classHierarchy == null) {
094: classHierarchy = new ClassHierarchy(scene);
095: }
096:
097: return classHierarchy;
098: }
099:
100: /** Get the type node for the given type. **/
101: public TypeNode typeNode(Type type) {
102: if (type == null) {
103: throw new InternalTypingException();
104: }
105:
106: type = transform.toInt(type);
107: TypeNode typeNode = typeNodeMap.get(type);
108:
109: if (typeNode == null) {
110: int id = typeNodeList.size();
111: typeNodeList.add(null);
112:
113: typeNode = make.typeNode(id, type, this );
114:
115: typeNodeList.set(id, typeNode);
116: typeNodeMap.put(type, typeNode);
117: }
118:
119: return typeNode;
120: }
121:
122: /** Returns a string representation of this object **/
123: public String toString() {
124: StringBuffer s = new StringBuffer();
125: boolean colon = false;
126:
127: s.append("ClassHierarchy:{");
128: for (TypeNode typeNode : typeNodeList) {
129: if (colon) {
130: s.append(",");
131: } else {
132: colon = true;
133: }
134:
135: s.append(typeNode);
136: }
137: s.append("}");
138:
139: return s.toString();
140: }
141:
142: /**
143: * Transforms boolean, byte, short and char into int.
144: **/
145: private static class ToInt extends TypeSwitch {
146: private Type result;
147: private final Type intType = IntType.v();
148:
149: private ToInt() {
150: }
151:
152: /** Transform boolean, byte, short and char into int. **/
153: Type toInt(Type type) {
154: type.apply(this );
155: return result;
156: }
157:
158: public void caseBooleanType(BooleanType type) {
159: result = intType;
160: }
161:
162: public void caseByteType(ByteType type) {
163: result = intType;
164: }
165:
166: public void caseShortType(ShortType type) {
167: result = intType;
168: }
169:
170: public void caseCharType(CharType type) {
171: result = intType;
172: }
173:
174: public void defaultCase(Type type) {
175: result = type;
176: }
177: }
178:
179: /**
180: * Creates new TypeNode instances usign the appropriate constructor.
181: **/
182: private static class ConstructorChooser extends TypeSwitch {
183: private int id;
184: private ClassHierarchy hierarchy;
185:
186: private TypeNode result;
187:
188: ConstructorChooser() {
189: }
190:
191: /** Create a new TypeNode instance for the type parameter. **/
192: TypeNode typeNode(int id, Type type, ClassHierarchy hierarchy) {
193: if (type == null || hierarchy == null) {
194: throw new InternalTypingException();
195: }
196:
197: this .id = id;
198: this .hierarchy = hierarchy;
199:
200: type.apply(this );
201:
202: return result;
203: }
204:
205: public void caseRefType(RefType type) {
206: result = new TypeNode(id, type, hierarchy);
207: }
208:
209: public void caseArrayType(ArrayType type) {
210: result = new TypeNode(id, type, hierarchy);
211: }
212:
213: public void defaultCase(Type type) {
214: result = new TypeNode(id, type, hierarchy);
215: }
216: }
217: }
|