KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > bcel > internal > verifier > structurals > OperandStack


1 package com.sun.org.apache.bcel.internal.verifier.structurals;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache BCEL" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache BCEL", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 import com.sun.org.apache.bcel.internal.generic.*;
58 import com.sun.org.apache.bcel.internal.verifier.exc.*;
59 import java.util.*;
60
61 /**
62  * This class implements a stack used for symbolic JVM stack simulation.
63  * [It's used an an operand stack substitute.]
64  * Elements of this stack are com.sun.org.apache.bcel.internal.generic.Type objects.
65  *
66  * @version $Id: OperandStack.java,v 1.1.1.1 2001/10/29 20:00:41 jvanzyl Exp $
67  * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
68  */

69 public class OperandStack{
70
71     /** We hold the stack information here. */
72     private ArrayList stack = new ArrayList();
73
74     /** The maximum number of stack slots this OperandStack instance may hold. */
75     private int maxStack;
76
77     /**
78      * Creates an empty stack with a maximum of maxStack slots.
79      */

80     public OperandStack(int maxStack){
81         this.maxStack = maxStack;
82     }
83
84     /**
85      * Creates an otherwise empty stack with a maximum of maxStack slots and
86      * the ObjectType 'obj' at the top.
87      */

88     public OperandStack(int maxStack, ObjectType obj){
89         this.maxStack = maxStack;
90         this.push(obj);
91     }
92     /**
93      * Returns a deep copy of this object; that means, the clone operates
94      * on a new stack. However, the Type objects on the stack are
95      * shared.
96      */

97     protected Object JavaDoc clone(){
98         OperandStack newstack = new OperandStack(this.maxStack);
99         newstack.stack = (ArrayList) this.stack.clone();
100         return newstack;
101     }
102
103     /**
104      * Clears the stack.
105      */

106     public void clear(){
107         stack = new ArrayList();
108     }
109
110     /**
111      * Returns true if and only if this OperandStack
112      * equals another, meaning equal lengths and equal
113      * objects on the stacks.
114      */

115     public boolean equals(Object JavaDoc o){
116         if (!(o instanceof OperandStack)) return false;
117         OperandStack s = (OperandStack) o;
118         return this.stack.equals(s.stack);
119     }
120
121     /**
122      * Returns a (typed!) clone of this.
123      *
124      * @see #clone()
125      */

126     public OperandStack getClone(){
127         return (OperandStack) this.clone();
128     }
129
130     /**
131      * Returns true IFF this OperandStack is empty.
132    */

133     public boolean isEmpty(){
134         return stack.isEmpty();
135     }
136
137     /**
138      * Returns the number of stack slots this stack can hold.
139      */

140     public int maxStack(){
141         return this.maxStack;
142     }
143
144     /**
145      * Returns the element on top of the stack. The element is not popped off the stack!
146      */

147     public Type peek(){
148         return peek(0);
149     }
150
151     /**
152    * Returns the element that's i elements below the top element; that means,
153    * iff i==0 the top element is returned. The element is not popped off the stack!
154    */

155     public Type peek(int i){
156         return (Type) stack.get(size()-i-1);
157     }
158
159     /**
160      * Returns the element on top of the stack. The element is popped off the stack.
161      */

162     public Type pop(){
163         Type e = (Type) stack.remove(size()-1);
164         return e;
165     }
166
167     /**
168      * Pops i elements off the stack. ALWAYS RETURNS "null"!!!
169      */

170     public Type pop(int i){
171         for (int j=0; j<i; j++){
172             pop();
173         }
174         return null;
175     }
176
177     /**
178      * Pushes a Type object onto the stack.
179      */

180     public void push(Type type){
181         if (type == null) throw new AssertionViolatedException("Cannot push NULL onto OperandStack.");
182         if (type == Type.BOOLEAN || type == Type.CHAR || type == Type.BYTE || type == Type.SHORT){
183             throw new AssertionViolatedException("The OperandStack does not know about '"+type+"'; use Type.INT instead.");
184         }
185         if (slotsUsed() >= maxStack){
186             throw new AssertionViolatedException("OperandStack too small, should have thrown proper Exception elsewhere. Stack: "+this);
187         }
188         stack.add(type);
189     }
190
191     /**
192      * Returns the size of this OperandStack; that means, how many Type objects there are.
193      */

194     int size(){
195         return stack.size();
196     }
197
198     /**
199      * Returns the number of stack slots used.
200      * @see #maxStack()
201      */

202     public int slotsUsed(){
203         /* XXX change this to a better implementation using a variable
204             that keeps track of the actual slotsUsed()-value monitoring
205             all push()es and pop()s.
206         */

207         int slots = 0;
208         for (int i=0; i<stack.size(); i++){
209             slots += peek(i).getSize();
210         }
211         return slots;
212     }
213     
214     /**
215      * Returns a String representation of this OperandStack instance.
216      */

217     public String JavaDoc toString(){
218         String JavaDoc s = "Slots used: "+slotsUsed()+" MaxStack: "+maxStack+".\n";
219         for (int i=0; i<size(); i++){
220             s+=peek(i)+" (Size: "+peek(i).getSize()+")\n";
221         }
222         return s;
223     }
224
225     /**
226      * Merges another stack state into this instance's stack state.
227      * See the Java Virtual Machine Specification, Second Edition, page 146: 4.9.2
228      * for details.
229      */

230     public void merge(OperandStack s){
231         if ( (slotsUsed() != s.slotsUsed()) || (size() != s.size()) )
232             throw new StructuralCodeConstraintException("Cannot merge stacks of different size:\nOperandStack A:\n"+this+"\nOperandStack B:\n"+s);
233         
234         for (int i=0; i<size(); i++){
235             // If the object _was_ initialized and we're supposed to merge
236
// in some uninitialized object, we reject the code (see vmspec2, 4.9.4, last paragraph).
237
if ( (! (stack.get(i) instanceof UninitializedObjectType)) && (s.stack.get(i) instanceof UninitializedObjectType) ){
238                 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
239             }
240             // Even harder, we're not initialized but are supposed to broaden
241
// the known object type
242
if ( (!(stack.get(i).equals(s.stack.get(i)))) && (stack.get(i) instanceof UninitializedObjectType) && (!(s.stack.get(i) instanceof UninitializedObjectType))){
243                 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
244             }
245             // on the other hand...
246
if (stack.get(i) instanceof UninitializedObjectType){ //if we have an uninitialized object here
247
if (! (s.stack.get(i) instanceof UninitializedObjectType)){ //that has been initialized by now
248
stack.set(i, ((UninitializedObjectType) (stack.get(i))).getInitialized() ); //note that.
249
}
250             }
251             if (! stack.get(i).equals(s.stack.get(i))){
252                 if ( (stack.get(i) instanceof ReferenceType) &&
253                             (s.stack.get(i) instanceof ReferenceType) ){
254                     stack.set(i, ((ReferenceType) stack.get(i)).firstCommonSuperclass((ReferenceType) (s.stack.get(i))));
255                 }
256                 else{
257                     throw new StructuralCodeConstraintException("Cannot merge stacks of different types:\nStack A:\n"+this+"\nStack B:\n"+s);
258                 }
259             }
260         }
261     }
262
263     /**
264      * Replaces all occurences of u in this OperandStack instance
265      * with an "initialized" ObjectType.
266      */

267     public void initializeObject(UninitializedObjectType u){
268         for (int i=0; i<stack.size(); i++){
269             if (stack.get(i) == u){
270                 stack.set(i, u.getInitialized());
271             }
272         }
273     }
274
275 }
276
Popular Tags