1 package org.kit.furia.fragment.soot;
2
3 import java.util.List;
4 import org.apache.log4j.Logger;
5 import org.kit.furia.exceptions.IRException;
6 import org.kit.furia.fragment.MTDFragmentAST;
7 import org.kit.furia.fragment.OBFragment;
8 import org.kit.furia.fragment.soot.representation.Frimp;
9 import org.kit.furia.fragment.soot.representation.internal.FExprBox;
10 import org.kit.furia.fragment.soot.representation.internal.FPhiExpr;
11 import org.kit.furia.fragment.soot.representation.internal.FSelfReference;
12 import org.kit.furia.misc.IntegerHolder;
13
14 import soot.Body;
15 import soot.Unit;
16 import soot.Value;
17 import soot.shimple.PhiExpr;
18 import soot.toolkits.graph.Block;
19 import soot.toolkits.graph.BlockGraph;
20 import soot.toolkits.graph.DirectedGraph;
21 import soot.toolkits.graph.ExceptionalBlockGraph;
22
23 import soot.ValueBox;
24
25 import java.util.Map;
26 import java.util.HashMap;
27
28 import soot.grimp.Grimp;
29 import soot.grimp.internal.ExprBox;
30 import soot.jimple.ArrayRef;
31 import soot.jimple.InstanceFieldRef;
32 import soot.jimple.StaticFieldRef;
33 import soot.jimple.internal.AbstractDefinitionStmt;
34 import soot.jimple.internal.JimpleLocal;
35
36 import java.util.LinkedList;
37 import java.util.Stack;
38 import java.util.Iterator;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class FragmentBuilder {
65
66 private static final Logger logger = Logger
67 .getLogger(FragmentBuilder.class);
68
69 private int hugeSlices;
70
71 private int smallSlices;
72
73 private final Map < Value, ValueBox > slices;
74
75
76
77 private final String methodName;
78
79 private int minAllowedSize;
80
81 private int maxAllowedSize;
82
83 public FragmentBuilder(final Body body, final BlockGraph graph,
84 int maxAllowedSize, int minAllowedSize) {
85 hugeSlices = 0;
86 smallSlices = 0;
87 this.minAllowedSize = minAllowedSize;
88 this.maxAllowedSize = maxAllowedSize;
89
90 methodName = body.getMethod().getSignature();
91 Map < Value, ValueBox > unexpandedSlices = extractUnexpandedSlices(graph);
92 slices = expandSlices(unexpandedSlices);
93
94 }
95
96 public Map < Value, ValueBox > getSlices() {
97 return slices;
98 }
99
100
101
102
103
104
105
106
107 private Map < Value, ValueBox > extractUnexpandedSlices(
108 final BlockGraph graph) {
109
110 final Map < Value, ValueBox > res = new HashMap();
111 final Iterator it = graph.getBlocks().iterator();
112 while (it.hasNext()) {
113 final Block block = (Block) it.next();
114 final Iterator blockIt = block.iterator();
115 while (blockIt.hasNext()) {
116 final Unit ins = (Unit) blockIt.next();
117
118 if (ins instanceof AbstractDefinitionStmt) {
119 final AbstractDefinitionStmt a = (AbstractDefinitionStmt) ins;
120 final ValueBox rightvb = new FExprBox(a.getRightOp());
121 Value left = a.getLeftOp();
122
123
124
125 assert left instanceof ArrayRef
126 || left instanceof JimpleLocal
127 || left instanceof InstanceFieldRef
128 || left instanceof StaticFieldRef : " left var instance of:"
129 + left.getClass().getName();
130
131 if (res.containsKey(left)) {
132
133
134 final ValueBox vb = res.get(left);
135 final Value v = vb.getValue();
136 if (v instanceof FPhiExpr) {
137 ((FPhiExpr) v).add(rightvb);
138 } else {
139
140 final List < Value > x = new LinkedList < Value >();
141 x.add(v);
142 x.add(rightvb.getValue());
143 FPhiExpr n = new FPhiExpr(x);
144 res.put(left, new FExprBox(n));
145 }
146 } else {
147 res.put(left, rightvb);
148 }
149 }
150 }
151 }
152 return res;
153 }
154
155 public int getTotalSlices() {
156 return this.slices.size();
157 }
158
159
160
161
162 private Map < Value, ValueBox > expandSlices(
163 final Map < Value, ValueBox > ue) {
164 this.hugeSlices = 0;
165 this.smallSlices = 0;
166 Map < Value, ValueBox > res = new HashMap < Value, ValueBox >();
167 Iterator < Value > it = ue.keySet().iterator();
168 while (it.hasNext()) {
169 Value k = it.next();
170 Stack < Value > j = new Stack < Value >();
171 j.push(k);
172 IntegerHolder i = new IntegerHolder(1);
173 try {
174
175 Value expanded = expandSliceAux(j, ue, k, i, maxAllowedSize);
176
177 int size = i.getValue();
178 if (size > maxAllowedSize) {
179 throw new HugeFragmentException();
180 } else if (size >= minAllowedSize) {
181 res.put(k, new FExprBox(expanded));
182
183 } else {
184 this.smallSlices++;
185 }
186 } catch (HugeFragmentException e) {
187 if (logger.isDebugEnabled()) {
188 logger.debug("Huge slice of size: " + i.getValue()
189 + " in: " + k + " " + this.methodName);
190 }
191 hugeSlices++;
192 }
193
194 }
195 return res;
196 }
197
198 private Value expandSliceAux(final Stack < Value > j,
199 final Map < Value, ValueBox > ue, final Value originalValue,
200 IntegerHolder i, int max_allowed_size)
201
202 throws HugeFragmentException {
203 if (i.getValue() > max_allowed_size) {
204
205 throw new HugeFragmentException();
206 }
207
208 Value rightToProcess;
209
210 if (null == ue.get(j.peek())) {
211 rightToProcess = Grimp.cloneIfNecessary(j.peek());
212 } else {
213
214 rightToProcess = Grimp.cloneIfNecessary(((ValueBox) ue
215 .get(j.peek())).getValue());
216 }
217
218 Iterator it = rightToProcess.getUseBoxes().iterator();
219 while (it.hasNext()) {
220 ValueBox vb = (ValueBox) it.next();
221 Value v = vb.getValue();
222
223
224 if (v.equals(originalValue)) {
225 vb.setValue(new FSelfReference());
226 continue;
227 }
228
229 if (j.contains(v)) {
230 continue;
231 }
232
233 if (!(v instanceof JimpleLocal || v instanceof InstanceFieldRef || v instanceof StaticFieldRef)) {
234 continue;
235 }
236 i.inc();
237 j.push(v);
238
239 vb.setValue(expandSliceAux(j, ue, originalValue, i,
240 max_allowed_size));
241
242 }
243 j.pop();
244 return rightToProcess;
245 }
246
247 public int getHugeSlices() {
248 return hugeSlices;
249 }
250
251 public String getMethodName() {
252 return methodName;
253 }
254
255
256
257
258
259
260 public void fillRepetitionCounts(
261 HashMap < String, IntegerHolder > repetitionCounts)
262 throws IRException {
263 try{
264
265 Iterator < Value > keys = slices.keySet().iterator();
266 while (keys.hasNext()) {
267 Value keyValue = keys.next();
268 Value value = slices.get(keyValue).getValue();
269 String fragment = Frimp.toQ(value);
270
271 IntegerHolder counter = repetitionCounts.get(fragment);
272 if (counter == null) {
273 counter = new IntegerHolder(0);
274 repetitionCounts.put(fragment, counter);
275 }
276 counter.inc();
277
278 }
279 }catch(Exception e){
280 throw new IRException(e);
281 }
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 public int getSmallSlices() {
321 return smallSlices;
322 }
323
324 }