KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > verifier > structurals > LocalVariables


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.verifier.structurals;
18
19
20 import org.apache.bcel.generic.ReferenceType;
21 import org.apache.bcel.generic.Type;
22 import org.apache.bcel.verifier.exc.AssertionViolatedException;
23 import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
24
25 /**
26  * This class implements an array of local variables used for symbolic JVM
27  * simulation.
28  *
29  * @version $Id: LocalVariables.java 386056 2006-03-15 11:31:56Z tcurdt $
30  * @author Enver Haase
31  */

32 public class LocalVariables{
33     /** The Type[] containing the local variable slots. */
34     private Type[] locals;
35
36     /**
37      * Creates a new LocalVariables object.
38      */

39     public LocalVariables(int maxLocals){
40         locals = new Type[maxLocals];
41         for (int i=0; i<maxLocals; i++){
42             locals[i] = Type.UNKNOWN;
43         }
44     }
45
46     /**
47      * Returns a deep copy of this object; i.e. the clone
48      * operates on a new local variable array.
49      * However, the Type objects in the array are shared.
50      */

51     protected Object JavaDoc clone(){
52         LocalVariables lvs = new LocalVariables(locals.length);
53         for (int i=0; i<locals.length; i++){
54             lvs.locals[i] = this.locals[i];
55         }
56         return lvs;
57     }
58
59     /**
60      * Returns the type of the local variable slot i.
61      */

62     public Type get(int i){
63         return locals[i];
64     }
65
66     /**
67      * Returns a (correctly typed) clone of this object.
68      * This is equivalent to ((LocalVariables) this.clone()).
69      */

70     public LocalVariables getClone(){
71         return (LocalVariables) this.clone();
72     }
73
74     /**
75      * Returns the number of local variable slots this
76      * LocalVariables instance has.
77      */

78     public int maxLocals(){
79         return locals.length;
80     }
81
82     /**
83      * Sets a new Type for the given local variable slot.
84      */

85     public void set(int i, Type type){
86         if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){
87             throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead.");
88         }
89         locals[i] = type;
90     }
91
92     /** @return a hash code value for the object.
93      */

94     public int hashCode() { return locals.length; }
95
96     /*
97      * Fulfills the general contract of Object.equals().
98      */

99     public boolean equals(Object JavaDoc o){
100         if (!(o instanceof LocalVariables)) {
101             return false;
102         }
103         LocalVariables lv = (LocalVariables) o;
104         if (this.locals.length != lv.locals.length) {
105             return false;
106         }
107         for (int i=0; i<this.locals.length; i++){
108             if (!this.locals[i].equals(lv.locals[i])){
109                 //System.out.println(this.locals[i]+" is not "+lv.locals[i]);
110
return false;
111             }
112         }
113         return true;
114     }
115     
116     /**
117      * Merges two local variables sets as described in the Java Virtual Machine Specification,
118      * Second Edition, section 4.9.2, page 146.
119      */

120     public void merge(LocalVariables lv){
121
122         if (this.locals.length != lv.locals.length){
123             throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
124         }
125
126         for (int i=0; i<locals.length; i++){
127             merge(lv, i);
128         }
129     }
130     
131     /**
132      * Merges a single local variable.
133      *
134      * @see #merge(LocalVariables)
135      */

136     private void merge(LocalVariables lv, int i){
137         try {
138         
139         // We won't accept an unitialized object if we know it was initialized;
140
// compare vmspec2, 4.9.4, last paragraph.
141
if ( (!(locals[i] instanceof UninitializedObjectType)) && (lv.locals[i] instanceof UninitializedObjectType) ){
142             throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
143         }
144         // Even harder, what about _different_ uninitialized object types?!
145
if ( (!(locals[i].equals(lv.locals[i]))) && (locals[i] instanceof UninitializedObjectType) && (lv.locals[i] instanceof UninitializedObjectType) ){
146             throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
147         }
148         // If we just didn't know that it was initialized, we have now learned.
149
if (locals[i] instanceof UninitializedObjectType){
150             if (! (lv.locals[i] instanceof UninitializedObjectType)){
151                 locals[i] = ((UninitializedObjectType) locals[i]).getInitialized();
152             }
153         }
154         if ((locals[i] instanceof ReferenceType) && (lv.locals[i] instanceof ReferenceType)){
155             if (! locals[i].equals(lv.locals[i])){ // needed in case of two UninitializedObjectType instances
156
Type sup = ((ReferenceType) locals[i]).getFirstCommonSuperclass((ReferenceType) (lv.locals[i]));
157
158                 if (sup != null){
159                     locals[i] = sup;
160                 }
161                 else{
162                     // We should have checked this in Pass2!
163
throw new AssertionViolatedException("Could not load all the super classes of '"+locals[i]+"' and '"+lv.locals[i]+"'.");
164                 }
165             }
166         }
167         else{
168             if (! (locals[i].equals(lv.locals[i])) ){
169 /*TODO
170                 if ((locals[i] instanceof org.apache.bcel.generic.ReturnaddressType) && (lv.locals[i] instanceof org.apache.bcel.generic.ReturnaddressType)){
171                     //System.err.println("merging "+locals[i]+" and "+lv.locals[i]);
172                     throw new AssertionViolatedException("Merging different ReturnAddresses: '"+locals[i]+"' and '"+lv.locals[i]+"'.");
173                 }
174 */

175                 locals[i] = Type.UNKNOWN;
176             }
177         }
178         } catch (ClassNotFoundException JavaDoc e) {
179         // FIXME: maybe not the best way to handle this
180
throw new AssertionViolatedException("Missing class: " + e.toString());
181         }
182     }
183
184     /**
185      * Returns a String representation of this object.
186      */

187     public String JavaDoc toString(){
188         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
189         for (int i=0; i<locals.length; i++){
190             sb.append(Integer.toString(i));
191             sb.append(": ");
192             sb.append(locals[i]);
193             sb.append("\n");
194         }
195         return sb.toString();
196     }
197
198     /**
199      * Replaces all occurences of u in this local variables set
200      * with an "initialized" ObjectType.
201      */

202     public void initializeObject(UninitializedObjectType u){
203         for (int i=0; i<locals.length; i++){
204             if (locals[i] == u){
205                 locals[i] = u.getInitialized();
206             }
207         }
208     }
209 }
210
Popular Tags