KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > evaluation > TracedStack


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard.evaluation;
22
23 import proguard.evaluation.value.*;
24
25 /**
26  * This Stack saves additional information with stack elements, to keep track
27  * of their origins and destinations.
28  * <p>
29  * The stack stores a given producer Value along with each Value it stores.
30  * It then generalizes a given collected Value with the producer Value
31  * of each Value it loads. The producer Value and the initial collected Value
32  * can be set; the generalized collected Value can be retrieved.
33  * <p>
34  * The stack also stores an empty consumer Value along with each Value it
35  * stores. It then generalizes and updates this consumer Value with the
36  * given producer Value each time the Value is loaded from the stack. The
37  * generalized consumer Value of each stack element can be retrieved.
38  *
39  * @author Eric Lafortune
40  */

41 public class TracedStack extends Stack
42 {
43     private Value producerValue;
44     private Value collectedProducerValue;
45     private Stack producerStack;
46     private Stack consumerStack;
47
48
49     public TracedStack(int maxSize)
50     {
51         super(maxSize);
52
53         producerStack = new Stack(maxSize);
54         consumerStack = new Stack(maxSize);
55     }
56
57
58     public TracedStack(TracedStack tracedStack)
59     {
60         super(tracedStack);
61
62         producerStack = new Stack(tracedStack.producerStack);
63         consumerStack = new Stack(tracedStack.consumerStack);
64     }
65
66
67     /**
68      * Sets the Value that will be stored along with all push and pop
69      * instructions.
70      */

71     public void setProducerValue(Value producerValue)
72     {
73         this.producerValue = producerValue;
74     }
75
76
77     /**
78      * Sets the initial Value with which all values stored along with load
79      * instructions will be generalized.
80      */

81     public void setCollectedProducerValue(Value collectedProducerValue)
82     {
83         this.collectedProducerValue = collectedProducerValue;
84     }
85
86
87     public Value getCollectedProducerValue()
88     {
89         return collectedProducerValue;
90     }
91
92
93     /**
94      * Gets the specified producer Value from the stack, without disturbing it.
95      * @param index the index of the stack element, counting from the bottom
96      * of the stack.
97      * @return the producer value at the specified position.
98      */

99     public Value getBottomProducerValue(int index)
100     {
101         return producerStack.getBottom(index);
102     }
103
104
105     /**
106      * Sets the specified producer Value on the stack, without disturbing it.
107      * @param index the index of the stack element, counting from the bottom
108      * of the stack.
109      * @param value the producer value to set.
110      */

111     public void setBottomProducerValue(int index, Value value)
112     {
113         producerStack.setBottom(index, value);
114     }
115
116
117     /**
118      * Gets the specified producer Value from the stack, without disturbing it.
119      * @param index the index of the stack element, counting from the top
120      * of the stack.
121      * @return the producer value at the specified position.
122      */

123     public Value getTopProducerValue(int index)
124     {
125         return producerStack.getTop(index);
126     }
127
128
129     /**
130      * Sets the specified producer Value on the stack, without disturbing it.
131      * @param index the index of the stack element, counting from the top
132      * of the stack.
133      * @param value the producer value to set.
134      */

135     public void setTopProducerValue(int index, Value value)
136     {
137         producerStack.setTop(index, value);
138     }
139
140
141     /**
142      * Gets the specified consumer Value from the stack, without disturbing it.
143      * @param index the index of the stack element, counting from the bottom of
144      * the stack.
145      * @return the consumer value at the specified position.
146      */

147     public Value getBottomConsumerValue(int index)
148     {
149         return ((MutableValue)consumerStack.getBottom(index)).getContainedValue();
150     }
151
152     /**
153      * Gets the specified consumer Value from the stack, without disturbing it.
154      * @param index the index of the stack element, counting from the top of the
155      * stack.
156      * @return the consumer value at the specified position.
157      */

158     public Value getTopConsumerValue(int index)
159     {
160         return ((MutableValue)consumerStack.getTop(index)).getContainedValue();
161     }
162
163
164     /**
165      * Sets the specified consumer Value on the stack, without disturbing it.
166      * @param index the index of the stack element, counting from the top
167      * of the stack.
168      * @param value the consumer value to set.
169      */

170     public void setTopConsumerValue(int index, Value value)
171     {
172         ((MutableValue)consumerStack.getTop(index)).setContainedValue(value);
173         consumerStack.setTop(index, new MutableValue());
174     }
175
176
177     // Implementations for Stack.
178

179     public void reset(int size)
180     {
181         super.reset(size);
182
183         producerStack.reset(size);
184         consumerStack.reset(size);
185     }
186
187     public void copy(TracedStack other)
188     {
189         super.copy(other);
190
191         producerStack.copy(other.producerStack);
192         consumerStack.copy(other.consumerStack);
193     }
194
195     public boolean generalize(TracedStack other)
196     {
197         return
198             super.generalize(other) |
199             producerStack.generalize(other.producerStack) |
200             consumerStack.generalize(other.consumerStack);
201     }
202
203     public void clear()
204     {
205         super.clear();
206
207         producerStack.clear();
208         consumerStack.clear();
209     }
210
211     public void removeTop(int index)
212     {
213         super.removeTop(index);
214
215         producerStack.removeTop(index);
216         consumerStack.removeTop(index);
217     }
218
219     public void push(Value value)
220     {
221         super.push(value);
222
223         tracePush();
224
225         // Account for the extra space required by Category 2 values.
226
if (value.isCategory2())
227         {
228             tracePush();
229         }
230     }
231
232     public Value pop()
233     {
234         Value value = super.pop();
235
236         tracePop();
237
238         // Account for the extra space required by Category 2 values.
239
if (value.isCategory2())
240         {
241             tracePop();
242         }
243
244         return value;
245     }
246
247     public void pop1()
248     {
249         super.pop1();
250
251         tracePop();
252     }
253
254     public void pop2()
255     {
256         super.pop2();
257
258         tracePop();
259         tracePop();
260     }
261
262     public void dup()
263     {
264         super.dup();
265
266         producerGeneralize(0);
267         producerStack.dup();
268
269         consumerPop();
270         consumerPush();
271         consumerPush();
272     }
273
274     public void dup_x1()
275     {
276         super.dup_x1();
277
278         producerGeneralize(0);
279         producerStack.dup_x1();
280
281         consumerPop();
282         consumerPush();
283         consumerStack.swap();
284         consumerPush();
285     }
286
287     public void dup_x2()
288     {
289         super.dup_x2();
290
291         producerGeneralize(0);
292         producerStack.dup_x2();
293
294         consumerPop();
295         consumerPush();
296         consumerStack.dup_x2();
297         consumerStack.pop();
298         consumerPush();
299     }
300
301     public void dup2()
302     {
303         super.dup2();
304
305         producerGeneralize(0);
306         producerGeneralize(1);
307         producerStack.dup2();
308
309         consumerPop();
310         consumerPop();
311         consumerPush();
312         consumerPush();
313         consumerPush();
314         consumerPush();
315     }
316
317     public void dup2_x1()
318     {
319         super.dup2_x1();
320
321         producerGeneralize(0);
322         producerGeneralize(1);
323         producerStack.dup2_x1();
324
325         consumerPop();
326         consumerPop();
327         consumerPush();
328         consumerPush();
329         consumerStack.dup2_x1();
330         consumerStack.pop2();
331         consumerPush();
332         consumerPush();
333     }
334
335     public void dup2_x2()
336     {
337         super.dup2_x2();
338
339         producerGeneralize(0);
340         producerGeneralize(1);
341         producerStack.dup2_x2();
342
343         consumerPop();
344         consumerPop();
345         consumerPush();
346         consumerPush();
347         consumerStack.dup2_x2();
348         consumerStack.pop2();
349         consumerPush();
350         consumerPush();
351     }
352
353     public void swap()
354     {
355         super.swap();
356
357         producerGeneralize(0);
358         producerGeneralize(1);
359         producerStack.swap();
360
361         consumerPop();
362         consumerPop();
363         consumerPush();
364         consumerPush();
365     }
366
367
368     // Implementations for Object.
369

370     public boolean equals(Object JavaDoc object)
371     {
372         if (object == null ||
373             this.getClass() != object.getClass())
374         {
375             return false;
376         }
377
378         TracedStack other = (TracedStack)object;
379
380         return super.equals(object) &&
381                this.producerStack.equals(other.producerStack) &&
382                this.consumerStack.equals(other.consumerStack);
383     }
384
385
386     public int hashCode()
387     {
388         return super.hashCode() ^
389                producerStack.hashCode() ^
390                consumerStack.hashCode();
391     }
392
393
394     public String JavaDoc toString()
395     {
396         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
397
398         for (int index = 0; index < this.size(); index++)
399         {
400             Value value = this.values[index];
401             Value producerValue = producerStack.getBottom(index);
402             Value consumerValue = consumerStack.getBottom(index);
403             buffer = buffer.append('[')
404                            .append(producerValue == null ? "empty" : producerValue.toString())
405                            .append('>')
406                            .append(value == null ? "empty" : value.toString())
407                            .append('>')
408                            .append(consumerValue == null ? "empty" : consumerValue.toString())
409                            .append(']');
410         }
411
412         return buffer.toString();
413     }
414
415
416     // Small utility methods.
417

418     private void tracePush()
419     {
420         producerPush();
421         consumerPush();
422     }
423
424
425     private void producerPush()
426     {
427         producerStack.push(producerValue);
428     }
429
430
431     private void consumerPush()
432     {
433         consumerStack.push(new MutableValue());
434     }
435
436
437     private void tracePop()
438     {
439         producerPop();
440         consumerPop();
441     }
442
443
444     private void producerPop()
445     {
446         Value popProducerValue = producerStack.pop();
447         producerGeneralize(popProducerValue);
448     }
449
450
451     private void consumerPop()
452     {
453         MutableValue popConsumerValue = (MutableValue)consumerStack.pop();
454         popConsumerValue.generalizeContainedValue(producerValue);
455     }
456
457
458     private void producerGeneralize(int index)
459     {
460         // We're not remembering the producers for dup/swap calls.
461
producerGeneralize(producerStack.getTop(index));
462     }
463
464
465     private void producerGeneralize(Value producerValue)
466     {
467         if (collectedProducerValue != null)
468         {
469             collectedProducerValue = collectedProducerValue.generalize(producerValue);
470         }
471     }
472 }
473
Popular Tags