KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > invoke > InlinerSafetyManager


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1999 Patrick Lam
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 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26 package soot.jimple.toolkits.invoke;
27
28 import soot.*;
29 import soot.jimple.*;
30 import java.util.*;
31
32 /** Methods for checking safety requirements for inlining. */
33 public class InlinerSafetyManager
34 {
35     // true if safe to inline
36
public static boolean checkSpecialInlineRestrictions(SootMethod container, SootMethod target, String JavaDoc options) {
37      // Check the body of the method to inline for specialinvoke's
38

39         boolean accessors=options.equals("accessors");
40         
41         Body inlineeBody = (JimpleBody) target.getActiveBody();
42         
43         Iterator unitsIt = inlineeBody.getUnits().iterator();
44         while (unitsIt.hasNext())
45         {
46             Stmt st = (Stmt)unitsIt.next();
47             if (st.containsInvokeExpr())
48             {
49                 InvokeExpr ie1 = (InvokeExpr)st.getInvokeExpr();
50                 
51                 if (ie1 instanceof SpecialInvokeExpr)
52                 {
53                     if((InlinerSafetyManager.specialInvokePerformsLookupIn(ie1, container.getDeclaringClass()) ||
54                       InlinerSafetyManager.specialInvokePerformsLookupIn(ie1, target.getDeclaringClass())))
55                     {
56                         return false;
57                         
58                     }
59                  
60                     SootMethod specialTarget = ie1.getMethod();
61                     
62                     if(specialTarget.isPrivate())
63                     {
64                         if(specialTarget.getDeclaringClass() != container.getDeclaringClass())
65                         {
66                             // Do not inline a call which contains a specialinvoke call to a private method outside
67
// the current class. This avoids a verifier error and we assume will not have a big
68
// impact because we are inlining methods bottom-up, so such a call will be rare
69

70                             if (!accessors)
71                                 return false;
72                         }
73                     }
74                 }
75               }
76         }
77     
78         
79         return true;
80     }
81     
82     public static boolean checkAccessRestrictions(SootMethod container, SootMethod target, String JavaDoc modifierOptions) {
83 // Check the body of the method to inline for
84
// method or field access restrictions
85
{
86             Body inlineeBody = (JimpleBody) target.getActiveBody();
87             
88             Iterator unitsIt = inlineeBody.getUnits().iterator();
89             while (unitsIt.hasNext())
90             {
91                 Stmt st = (Stmt)unitsIt.next();
92                 if (st.containsInvokeExpr())
93                 {
94                     InvokeExpr ie1 = (InvokeExpr)st.getInvokeExpr();
95                     
96                     if (!AccessManager.ensureAccess(container, ie1.getMethod(), modifierOptions))
97                         return false;
98                   }
99
100                 if (st instanceof AssignStmt)
101                 {
102                     Value lhs = ((AssignStmt)st).getLeftOp();
103                     Value rhs = ((AssignStmt)st).getRightOp();
104
105                     if (lhs instanceof FieldRef &&
106                         !AccessManager.ensureAccess(container, ((FieldRef)lhs).getField(),
107                                                     modifierOptions))
108                         return false;
109                         
110                                                                                
111                     if (rhs instanceof FieldRef &&
112                         !AccessManager.ensureAccess(container, ((FieldRef)rhs).getField(),
113                                                     modifierOptions))
114                         return false;
115                         
116                 }
117             }
118         }
119         
120         return true;
121          
122     }
123     
124     /** Returns true if this method can be inlined at the given site.
125         Will try as hard as it can to change things to allow
126         inlining (modifierOptions controls what it's allowed to do:
127         safe, unsafe and nochanges)
128         
129         Returns false otherwise.
130     */

131     
132     public static boolean ensureInlinability(SootMethod target,
133                                              Stmt toInline,
134                                              SootMethod container,
135                                              String JavaDoc modifierOptions)
136     {
137         if(!InlinerSafetyManager.canSafelyInlineInto(target, toInline, container)) {
138             //System.out.println("canSafelyInlineInto failed");
139
return false;
140         }
141     
142         if(!AccessManager.ensureAccess(container, target, modifierOptions)) {
143             //System.out.println("ensure access failed");
144
return false;
145         }
146             
147         if (!checkSpecialInlineRestrictions(container, target, modifierOptions)) {
148             //System.out.println("checkSpecialInlineRestrictions failed");
149
return false;
150         }
151         
152         if (!checkAccessRestrictions(container, target, modifierOptions)) {
153             //System.out.println("checkAccessRestrictions failed");
154
return false;
155         }
156         
157         return true;
158     }
159     
160     /** Checks the safety criteria enumerated in section 3.1.4
161      * (Safety Criteria for Method Inlining) of Vijay's thesis. */

162     private static boolean canSafelyInlineInto(SootMethod inlinee,
163                                               Stmt toInline,
164                                               SootMethod container)
165
166     {
167         /* first, check the simple (one-line) safety criteria. */
168
169         // Rule 0: Don't inline constructors.
170
if (inlinee.getName().equals("<init>"))
171             return false;
172
173         // Rule 2: inlinee != container.
174
if (inlinee.getSignature().equals(container.getSignature()))
175             return false;
176
177         // Rule 3: inlinee is neither native nor abstract.
178
if (inlinee.isNative() || inlinee.isAbstract())
179             return false;
180
181         // Ok, that wraps up the simple criteria. Now for the more
182
// complicated criteria.
183

184         // Rule 4: Don't inline away IllegalAccessErrors of the original
185
// source code (e.g. by moving a call to a private method
186
// *from* a bad class *to* a good class) occuring in the
187
// toInline statement.
188
// Does not occur for static methods, because there is no base?
189

190         InvokeExpr ie = (InvokeExpr)toInline.getInvokeExpr();
191         Value base = (ie instanceof InstanceInvokeExpr) ?
192             ((InstanceInvokeExpr)ie).getBase() : null;
193
194         if (base != null && invokeThrowsAccessErrorIn(((RefType)base.getType()).getSootClass(), inlinee, container))
195             return false;
196
197         // Rule 5: Don't inline away any class, method or field access
198
// (in inlinee) resulting in an IllegalAccess error.
199

200         // Rule 6: Don't introduce a spurious IllegalAccessError from
201
// inlining (by twiddling modifiers).
202

203         // This is better handled by a pre-phase Scene transformation.
204
// Inliner Safety should just report the absence of such
205
// IllegalAccessErrors after the transformation (and, conversely,
206
// their presence without the twiddling.)
207

208         // Rule 7: Don't change semantics of program by moving
209
// an invokespecial.
210
if (ie instanceof SpecialInvokeExpr &&
211                 (specialInvokePerformsLookupIn(ie, inlinee.getDeclaringClass()) ||
212                 specialInvokePerformsLookupIn(ie, container.getDeclaringClass())))
213             return false;
214
215         return true;
216     }
217
218     /** Returns true if any of the following cases holds:
219      * 1. inlinee is private, but container.declaringClass() !=
220      * inlinee.declaringClass(); or,
221      * 2. inlinee is package-visible, and its package differs from
222      * that of container; or,
223      * 3. inlinee is protected, and either:
224      * a. inlinee doesn't belong to container.declaringClass,
225      * or any superclass of container;
226      * b. the class of the base is not a (non-strict) subclass
227      * of container's declaringClass.
228      * The base class may be null, in which case 3b is omitted.
229      * (for instance, for a static method invocation.) */

230     private static boolean invokeThrowsAccessErrorIn(SootClass base,
231                                                      SootMethod inlinee,
232                                                      SootMethod container)
233     {
234         SootClass inlineeClass = inlinee.getDeclaringClass();
235         SootClass containerClass = container.getDeclaringClass();
236
237         // Condition 1 above.
238
if (inlinee.isPrivate() &&
239                 !inlineeClass.getName().equals(containerClass.getName()))
240             return true;
241
242         // Condition 2. Check the package names.
243
if (!inlinee.isPrivate() && !inlinee.isProtected()
244             && !inlinee.isPublic())
245         {
246             if (!inlineeClass.getPackageName().equals
247                      (containerClass.getPackageName()))
248                 return true;
249         }
250
251         // Condition 3.
252
if (inlinee.isProtected())
253         {
254             Hierarchy h = Scene.v().getActiveHierarchy();
255             boolean saved = false;
256
257             // protected means that you can be accessed by your children.
258
// i.e. container must be in a child of inlinee.
259
if (h.isClassSuperclassOfIncluding(inlineeClass, containerClass) ||
260                 ((base != null) &&
261                  h.isClassSuperclassOfIncluding(base, containerClass)))
262                 saved = true;
263
264             if (!saved)
265                 return true;
266         }
267
268         return false;
269     }
270
271     // m is the method being called; container is the class from which m
272
// is being called.
273
static boolean specialInvokePerformsLookupIn
274         (InvokeExpr ie, SootClass containerClass)
275     {
276         // If all of the conditions are true, a lookup is performed.
277
SootMethod m = ie.getMethod();
278
279
280         if (m.getName().equals("<init>"))
281         {
282             return false;
283         }
284
285         if (m.isPrivate())
286         {
287             return false;
288         }
289
290         Hierarchy h = Scene.v().getActiveHierarchy();
291
292         if (!h.isClassSuperclassOf(m.getDeclaringClass(),
293                                    containerClass))
294             return false;
295
296         // ACC_SUPER must always be set, eh?
297

298         return true;
299     }
300 }
301
Popular Tags