KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > VariableStack


1 /* VariableStack Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: VariableStack.java,v 1.8.4.1 2002/05/28 17:34:09 hoenicke Exp $
18  */

19
20 package jode.flow;
21 import jode.decompiler.LocalInfo;
22 import jode.expr.Expression;
23 import jode.expr.LocalLoadOperator;
24 import jode.expr.Operator;
25
26 /**
27  * This class represents the state of the stack at various points in
28  * the program. Each entry is a anonymous local, which is used instead
29  * of the PUSH / stack_i statements. <p>
30  *
31  * This class is immutable, but note, that the local infos can get merged.
32  * @see FlowBlock.mapStackToLocal
33  * @see FlowBlock.removePush
34  */

35 public class VariableStack {
36     public final static VariableStack EMPTY = new VariableStack();
37
38     final LocalInfo[] stackMap;
39
40     private VariableStack() {
41     stackMap = new LocalInfo[0];
42     }
43
44     private VariableStack(LocalInfo[] stack) {
45     stackMap = stack;
46     }
47
48     public boolean isEmpty() {
49     return stackMap.length == 0;
50     }
51
52     public VariableStack pop(int count) {
53     LocalInfo[] newStack = new LocalInfo[stackMap.length - count];
54     System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count);
55     return new VariableStack(newStack);
56     }
57     
58     public VariableStack push(LocalInfo li) {
59     return poppush(0, li);
60     }
61     
62     public VariableStack poppush(int count, LocalInfo li) {
63     LocalInfo[] newStack = new LocalInfo[stackMap.length - count + 1];
64     System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count);
65     newStack[stackMap.length - count] = li;
66     return new VariableStack(newStack);
67     }
68     
69     public VariableStack peek(int count) {
70     LocalInfo[] peeked = new LocalInfo[count];
71     System.arraycopy(stackMap, stackMap.length - count, peeked, 0, count);
72     return new VariableStack(peeked);
73     }
74
75     public void merge(VariableStack other) {
76     if (stackMap.length != other.stackMap.length)
77         throw new IllegalArgumentException JavaDoc("stack length differs");
78     for (int i=0; i<stackMap.length; i++) {
79         if (stackMap[i].getType().stackSize()
80         != other.stackMap[i].getType().stackSize())
81         throw new IllegalArgumentException JavaDoc
82             ("stack element length differs at "+i);
83         stackMap[i].combineWith(other.stackMap[i]);
84     }
85     }
86
87     /**
88      * Merge to VariableStacks. Either one may be null, in which case
89      * the other is returned.
90      */

91     public static VariableStack merge(VariableStack first,
92                       VariableStack second) {
93     if (first == null)
94         return second;
95     else if (second == null)
96         return first;
97     first.merge(second);
98     return first;
99     }
100
101     public Expression mergeIntoExpression(Expression expr) {
102     /* assert expr.getFreeOperandCount() == stackMap.length */
103
104     for (int i = stackMap.length-1; i >= 0; i--) {
105 // if (!used.contains(stackMap[i]))
106
// used.addElement(stackMap[i]);
107
expr = expr.addOperand
108         (new LocalLoadOperator(stackMap[i].getType(), null,
109                        stackMap[i]));
110     }
111     return expr;
112     }
113
114     public VariableStack executeSpecial(SpecialBlock special) {
115     if (special.type == special.POP) {
116         int popped = 0;
117         int newLength = stackMap.length;
118         while (popped < special.count) {
119         newLength--;
120         popped += stackMap[newLength].getType().stackSize();
121         }
122         if (popped != special.count)
123         throw new IllegalArgumentException JavaDoc("wrong POP");
124         LocalInfo[] newStack = new LocalInfo[newLength];
125         System.arraycopy(stackMap, 0, newStack, 0, newLength);
126         return new VariableStack(newStack);
127     } else if (special.type == special.DUP) {
128         int popped = 0;
129         int numDup = 0;
130         int startDup = stackMap.length;
131         while (popped < special.count) {
132         startDup--;
133         numDup++;
134         popped += stackMap[startDup].getType().stackSize();
135         }
136         if (popped != special.count)
137         throw new IllegalArgumentException JavaDoc("wrong DUP");
138         int destDup = startDup;
139         int depth = 0;
140         while (depth < special.depth) {
141         destDup--;
142         depth += stackMap[destDup].getType().stackSize();
143         }
144         if (depth != special.depth)
145         throw new IllegalArgumentException JavaDoc("wrong DUP");
146         LocalInfo[] newStack = new LocalInfo[stackMap.length + numDup];
147         System.arraycopy(stackMap, 0, newStack, 0, destDup);
148         System.arraycopy(stackMap, startDup, newStack, destDup, numDup);
149         System.arraycopy(stackMap, destDup, newStack, destDup + numDup,
150                  startDup - destDup);
151         System.arraycopy(stackMap, startDup, newStack, startDup + numDup,
152                  numDup);
153         return new VariableStack(newStack);
154     } else if (special.type == special.SWAP) {
155         LocalInfo[] newStack = new LocalInfo[stackMap.length];
156         System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - 2);
157         if (stackMap[stackMap.length-2].getType().stackSize() != 1
158         || stackMap[stackMap.length-1].getType().stackSize() != 1)
159         throw new IllegalArgumentException JavaDoc("wrong SWAP");
160         newStack[stackMap.length-2] = stackMap[stackMap.length-1];
161         newStack[stackMap.length-1] = stackMap[stackMap.length-2];
162         return new VariableStack(newStack);
163     } else
164         throw new jode.AssertError("Unknown SpecialBlock");
165     }
166
167     public String JavaDoc toString() {
168         StringBuffer JavaDoc result = new StringBuffer JavaDoc("[");
169         for (int i=0; i < stackMap.length; i++) {
170             if (i>0)
171                 result.append(", ");
172             result.append(stackMap[i].getName());
173         }
174         return result.append("]").toString();
175     }
176 }
177
Popular Tags