KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > callgraph > VirtualCalls


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2003 Ondrej Lhotak
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 package soot.jimple.toolkits.callgraph;
21 import soot.*;
22 import soot.jimple.*;
23 import java.util.*;
24 import soot.util.*;
25 import soot.util.queue.*;
26
27 /** Resolves virtual calls.
28  * @author Ondrej Lhotak
29  */

30 public final class VirtualCalls
31 {
32     public VirtualCalls( Singletons.Global g ) {}
33     public static VirtualCalls v() { return G.v().soot_jimple_toolkits_callgraph_VirtualCalls(); }
34
35     private LargeNumberedMap typeToVtbl =
36         new LargeNumberedMap( Scene.v().getTypeNumberer() );
37
38     public SootMethod resolveSpecial( SpecialInvokeExpr iie, NumberedString subSig, SootMethod container ) {
39         SootMethod target = iie.getMethod();
40         /* cf. JVM spec, invokespecial instruction */
41         if( Scene.v().getOrMakeFastHierarchy()
42                 .canStoreType( container.getDeclaringClass().getType(),
43                     target.getDeclaringClass().getType() )
44             && container.getDeclaringClass().getType() !=
45                 target.getDeclaringClass().getType()
46             && !target.getName().equals( "<init>" )
47             && subSig != sigClinit ) {
48
49             return resolveNonSpecial(
50                     container.getDeclaringClass().getSuperclass().getType(),
51                     subSig );
52         } else {
53             return target;
54         }
55     }
56
57     public SootMethod resolveNonSpecial( RefType t, NumberedString subSig ) {
58         SmallNumberedMap vtbl = (SmallNumberedMap) typeToVtbl.get( t );
59         if( vtbl == null ) {
60             typeToVtbl.put( t, vtbl =
61                     new SmallNumberedMap( Scene.v().getMethodNumberer() ) );
62         }
63         SootMethod ret = (SootMethod) vtbl.get( subSig );
64         if( ret != null ) return ret;
65         SootClass cls = ((RefType)t).getSootClass();
66         if( cls.declaresMethod( subSig ) ) {
67             SootMethod m = cls.getMethod( subSig );
68             if( m.isConcrete() || m.isNative() ) {
69                 ret = cls.getMethod( subSig );
70             }
71         } else {
72             if( cls.hasSuperclass() ) {
73                 ret = resolveNonSpecial( cls.getSuperclass().getType(), subSig );
74             }
75         }
76         vtbl.put( subSig, ret );
77         return ret;
78     }
79
80     private Map baseToSubTypes = new HashMap();
81
82     public void resolve( Type t, Type declaredType, NumberedString subSig, SootMethod container, ChunkedQueue targets ) {
83         resolve(t, declaredType, null, subSig, container, targets);
84     }
85     public void resolve( Type t, Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue targets ) {
86         if( declaredType instanceof ArrayType ) declaredType = RefType.v("java.lang.Object");
87         if( sigType instanceof ArrayType ) sigType = RefType.v("java.lang.Object");
88         if( t instanceof ArrayType ) t = RefType.v( "java.lang.Object" );
89         if( declaredType != null && !Scene.v().getOrMakeFastHierarchy()
90                 .canStoreType( t, declaredType ) ) {
91             return;
92         }
93         if( sigType != null && !Scene.v().getOrMakeFastHierarchy()
94                 .canStoreType( t, sigType ) ) {
95             return;
96         }
97         if( t instanceof RefType ) {
98             SootMethod target = resolveNonSpecial( (RefType) t, subSig );
99             if( target != null ) targets.add( target );
100         } else if( t instanceof AnySubType ) {
101             RefType base = ((AnySubType)t).getBase();
102
103             List subTypes = (List) baseToSubTypes.get(base);
104             if( subTypes != null ) {
105                 for( Iterator stIt = subTypes.iterator(); stIt.hasNext(); ) {
106                     final Type st = (Type) stIt.next();
107                     resolve( st, declaredType, sigType, subSig, container, targets );
108                 }
109                 return;
110             }
111
112             baseToSubTypes.put(base, subTypes = new ArrayList() );
113
114             subTypes.add(base);
115
116             LinkedList worklist = new LinkedList();
117             HashSet workset = new HashSet();
118             FastHierarchy fh = Scene.v().getOrMakeFastHierarchy();
119             SootClass cl = base.getSootClass();
120
121             if( workset.add( cl ) ) worklist.add( cl );
122             while( !worklist.isEmpty() ) {
123                 cl = (SootClass) worklist.removeFirst();
124                 if( cl.isInterface() ) {
125                     for( Iterator cIt = fh.getAllImplementersOfInterface(cl).iterator(); cIt.hasNext(); ) {
126                         final SootClass c = (SootClass) cIt.next();
127                         if( workset.add( c ) ) worklist.add( c );
128                     }
129                 } else {
130                     if( cl.isConcrete() ) {
131                         resolve( cl.getType(), declaredType, sigType, subSig, container, targets );
132                         subTypes.add(cl.getType());
133                     }
134                     for( Iterator cIt = fh.getSubclassesOf( cl ).iterator(); cIt.hasNext(); ) {
135                         final SootClass c = (SootClass) cIt.next();
136                         if( workset.add( c ) ) worklist.add( c );
137                     }
138                 }
139             }
140         } else if( t instanceof NullType ) {
141         } else {
142             throw new RuntimeException JavaDoc( "oops "+t );
143         }
144     }
145     
146     public final NumberedString sigClinit =
147         Scene.v().getSubSigNumberer().findOrAdd("void <clinit>()");
148     public final NumberedString sigStart =
149         Scene.v().getSubSigNumberer().findOrAdd("void start()");
150     public final NumberedString sigRun =
151         Scene.v().getSubSigNumberer().findOrAdd("void run()");
152 }
153
154
155
Popular Tags