KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hansel > stack > StackFactory


1
2 package org.hansel.stack;
3
4 import java.util.Hashtable JavaDoc;
5 import java.util.SortedSet JavaDoc;
6 import java.util.TreeSet JavaDoc;
7
8 public class StackFactory {
9  /* private Hashtable result;
10     private InstructionList il;
11     private SortedSet workList;
12     private MethodGen method;
13
14     public StackFactory(MethodGen method) {
15         this.method = method;
16         this.result = new Hashtable();
17         this.il = method.getInstructionList();
18         this.workList = new TreeSet();
19
20         SymbolicStack stack = new SymbolicStack(new MethodInfo(method));
21
22         // Add emthod start
23         workList.add(new WorkListEntry(il.getStart(), stack));
24  
25         // Add exception handlers.
26         CodeExceptionGen[] ceg = method.getExceptionHandlers();
27             
28         for (int i=0; i<ceg.length; i++) {
29             ObjectType excType = new ObjectType("java.lang.Exception");
30             workList.add(new WorkListEntry(ceg[i].getHandlerPC(),
31                                            stack.push(new StackEntry("Exception",
32                                                                      excType))));
33         }
34     }
35
36     public Hashtable getResult() {
37         return result;
38     }
39
40     private void addWorkList(InstructionHandle ih, SymbolicStack stack) {
41         WorkListEntry entry = new WorkListEntry(ih, stack);
42         if (!workList.contains(entry)) {
43             workList.add(entry);
44         }
45     }
46
47     public void calculateMethodStacks() {
48         try {
49             while (workList.size() > 0) {
50                 WorkListEntry wle = (WorkListEntry) workList.first();
51                 workList.remove(wle);
52
53                 // Execute instruction
54                 calculateStackEntries(wle.getInstructionHandle(),
55                                       wle.getStack());
56          
57             }
58         } catch (NullPointerException e) {
59             logBugWarning(e);
60         } catch (UnsupportedOperationException e) {
61             logBugWarning(e);
62         } catch (EmptyStackException e) {
63             logBugWarning(e);
64         }
65     }
66
67     private void logBugWarning(Exception e) {
68         System.out.println("WARNING: Found bug while decompiling expression.");
69         System.out.println("This does not change the coverage results.");
70         System.out.println("Class: " + method.getClassName());
71         System.out.println("Method: " + method);
72         System.out.println("Method-Bytecode: " + method.getMethod().getCode());
73         System.out.println("Please report this bug (including the following stacktrace and the compiler you are using)"
74                            + " at \n http://sourceforge.net/tracker/?group_id=54171&atid=472899");
75         e.printStackTrace();
76     }
77
78     private int available(InstructionHandle ih) {
79         int available = 0;
80         while (ih != null) {
81             available++;
82             ih = ih.getNext();
83         }
84         
85         return available;
86     }
87     
88     private boolean isComplexOperator(InstructionHandle[] instrs) {
89         if (!((instrs[1].getInstruction() instanceof ICONST) &&
90               (instrs[2].getInstruction() instanceof GOTO) &&
91               (instrs[3].getInstruction() instanceof ICONST))) {
92             return false;
93         }
94        
95         int value1 = ((ICONST) instrs[1].getInstruction()).getValue().intValue();
96         int value2 = ((ICONST) instrs[3].getInstruction()).getValue().intValue();
97
98         if ((value1 != 1) || (value2 != 0)) {
99             return false;
100         }
101
102         if (((IfInstruction) instrs[0].getInstruction()).getTarget() != instrs[3]) {
103             return false;
104         }
105       
106         if (((GOTO) instrs[2].getInstruction()).getTarget() != instrs[4]) {
107             return false;
108         }
109
110         return true;
111     }
112
113     private boolean isComplexOperator2(InstructionHandle[] instrs) {
114         if (!((instrs[1].getInstruction() instanceof ICONST) &&
115               (instrs[2].getInstruction() instanceof GOTO) &&
116               (instrs[3].getInstruction() instanceof ICONST))) {
117             return false;
118         }
119        
120         int value1 = ((ICONST) instrs[1].getInstruction()).getValue().intValue();
121         int value2 = ((ICONST) instrs[3].getInstruction()).getValue().intValue();
122
123         if ((value1 != 0) || (value2 != 1)) {
124             return false;
125         }
126
127         if (((IfInstruction) instrs[0].getInstruction()).getTarget() != instrs[3]) {
128             return false;
129         }
130       
131         if (((GOTO) instrs[2].getInstruction()).getTarget() != instrs[4]) {
132             return false;
133         }
134
135         return true;
136     }
137
138     private void checkComplexOperator(SymbolicStack stack,
139                                       InstructionHandle ih) {
140         if (!(ih.getInstruction() instanceof IfInstruction)) {
141             return;
142         }
143
144         if (available(ih) <= 5) {
145             return;
146         }
147
148         // Special case: Sometimes the compiler translates
149         // boolean arithmetic into a complex set of instructions.
150         // For example !(expression) is translated as
151         // 1: aconst_0
152         // 2: [calculate expression]
153         // 3: ifeq 6
154         // 4: iconst_0
155         // 5: goto 7
156         // 6: iconst_1
157         // 7: following code
158         // This code tries to find these code fragments
159         // and generate the correct stack.
160         InstructionHandle[] instructions = new InstructionHandle[5];
161         instructions[0] = ih;
162         for (int i=1; i<instructions.length; i++) {
163             instructions[i] = instructions[i-1].getNext();
164         }
165         
166         if (isComplexOperator(instructions)) {
167             StackEntry newEntry = new ComplexOr(instructions[1],
168                                                 result,
169                                                 il).getStackEntry();
170
171             SymbolicStack newStack = stack;
172             int consume = ((IfInstruction) ih.getInstruction()).consumeStack(null);
173             for (int i=0; i<consume; i++) {
174                 newStack = newStack.pop();
175             }
176
177             newStack = newStack.push(newEntry);
178             addWorkList(instructions[4], newStack);
179         }
180         else if (isComplexOperator2(instructions)) {
181             StackEntry newEntry = new ComplexOr(instructions[1],
182                                                 result,
183                                                 il).getStackEntry();
184             newEntry = new NotOp(newEntry);
185
186             SymbolicStack newStack = stack;
187             int consume = ((IfInstruction) ih.getInstruction()).consumeStack(null);
188             for (int i=0; i<consume; i++) {
189                 newStack = newStack.pop();
190             }
191
192             newStack = newStack.push(newEntry);
193             addWorkList(instructions[4], newStack);
194         }
195     }
196
197     private void calculateStackEntries(InstructionHandle ih,
198                                        SymbolicStack stack) {
199         if (result.containsKey(ih)) {
200             // Nothing to do
201             return;
202         } else {
203             result.put(ih, stack);
204         }
205
206         // Try to resolve complex operators.
207         checkComplexOperator(stack, ih);
208
209         // Special treatment for jsr, because continueing in the current
210         // execution thread and jumping to the subroutine is handled
211         // differently
212         if (ih.getInstruction() instanceof JsrInstruction) {
213             JsrInstruction jsr = (JsrInstruction) ih.getInstruction();
214             addWorkList(jsr.getTarget(),
215                         stack.emptyStack().push(new StackEntry("ReturnAddr",
216                                                                Type.UNKNOWN)));
217         }
218
219         // Calculate new stack
220         SymbolicStack newStack = null;
221
222         try {
223             newStack = stack.executeInstruction(ih.getInstruction());
224         } catch (EmptyStackException e) {
225             throw new EmptyStackException("When executing: " + ih.toString());
226         }
227        
228         // Execute all possible paths
229         InstructionHandle[] followUp = getFollowUpInstr(ih);
230         for (int i=0; i<followUp.length; i++) {
231             addWorkList(followUp[i], newStack);
232         }
233     }
234
235     private InstructionHandle[] getFollowUpInstr(InstructionHandle ih) {
236         Instruction instr = ih.getInstruction();
237
238         if (instr instanceof Select) {
239             InstructionHandle[] targets = ((Select) instr).getTargets();
240             InstructionHandle[] result = new InstructionHandle[targets.length + 1];
241             System.arraycopy(targets, 0, result, 0, targets.length);
242             result[result.length - 1] = ((Select) instr).getTarget();
243             return result;
244         } else if (instr instanceof IfInstruction) {
245             BranchInstruction bi = ((BranchInstruction) instr);
246             
247             return new InstructionHandle[] {ih.getNext(),
248                                             bi.getTarget()};
249         } else if (instr instanceof GotoInstruction) {
250             BranchInstruction bi = ((BranchInstruction) instr);
251             return new InstructionHandle[] {bi.getTarget()};
252         } else if ((instr instanceof ReturnInstruction) ||
253                    (instr instanceof RET) ||
254                    (instr instanceof ATHROW)) {
255             return new InstructionHandle[0];
256         }
257         
258         return new InstructionHandle[] {ih.getNext()};
259     }
260
261     private class WorkListEntry implements Comparable {
262         private InstructionHandle ih;
263         private SymbolicStack stack;
264
265         public WorkListEntry(InstructionHandle ih, SymbolicStack stack) {
266             this.ih = ih;
267             this.stack = stack;
268         }
269
270         public int compareTo(Object o) {
271             return ih.getPosition() - ((WorkListEntry) o).ih.getPosition();
272         }
273
274         public boolean equals(Object o) {
275             return ih == ((WorkListEntry) o).ih;
276         }
277
278         public InstructionHandle getInstructionHandle() {
279             return ih;
280         }
281
282         public SymbolicStack getStack() {
283             return stack;
284         }
285     }*/

286 }
287
Popular Tags