KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > shimple > toolkits > graph > ValueGraph


1 /////////////////////////
2
// Confusion on new Node(Value value)
3
// is value leftOp or rightOp?
4
/////////////////////////
5

6
7
8
9 /* Soot - a J*va Optimization Framework
10  * Copyright (C) 2003 Navindra Umanee <navindra@cs.mcgill.ca>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the
24  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */

27
28 package soot.shimple.toolkits.graph;
29
30 import soot.*;
31 import soot.jimple.*;
32 import soot.util.*;
33 import soot.shimple.*;
34 import soot.toolkits.graph.*;
35 import java.util.*;
36
37 // consider implementing DirectedGraph
38
public class ValueGraph
39 {
40     // can we handle field writes/reads?
41
// Issues: - does the field write DOMINATE field uses?
42
// - do intervening method calls have SIDE-EFFECTs?
43
// Affects fields whether of simple type or ref type
44
// - CONCURRENT writes?
45

46     protected Map localToNode;
47     protected Map nodeToLocal;
48     protected List nodeList;
49     protected int currentNodeNumber;
50     
51     public ValueGraph(BlockGraph cfg)
52     {
53         if(!(cfg.getBody() instanceof ShimpleBody))
54             throw new RuntimeException JavaDoc("ValueGraph requires SSA form");
55
56         localToNode = new HashMap();
57         nodeToLocal = new HashMap();
58         nodeList = new ArrayList();
59         currentNodeNumber = 0;
60         PseudoTopologicalOrderer pto = new PseudoTopologicalOrderer();
61         List blocks = pto.newList(cfg);
62
63         for(Iterator blocksIt = blocks.iterator(); blocksIt.hasNext();){
64             Block block = (Block) blocksIt.next();
65             for(Iterator blockIt = block.iterator(); blockIt.hasNext();)
66                 handleStmt((Stmt) blockIt.next());
67         }
68
69         for(Iterator nodesIt = nodeList.iterator(); nodesIt.hasNext();){
70             Node node = (Node) nodesIt.next();
71             node.patchStubs();
72         }
73     }
74
75     protected void handleStmt(Stmt stmt)
76     {
77         if(!(stmt instanceof DefinitionStmt))
78             return;
79         DefinitionStmt dStmt = (DefinitionStmt) stmt;
80
81         Value leftOp = dStmt.getLeftOp();
82         if(!(leftOp instanceof Local))
83             return;
84
85         Value rightOp = dStmt.getRightOp();
86         Node node = fetchGraph(rightOp);
87         localToNode.put(leftOp, node);
88
89         // only update for non-trivial assignments and non-stubs
90
if(!(rightOp instanceof Local) && !node.isStub())
91             nodeToLocal.put(node, leftOp);
92     }
93     
94     protected Node fetchNode(Value value)
95     {
96         Node ret = null;
97
98         if(value instanceof Local){
99             // assumption: the local definition has already been processed
100
ret = getNode(value);
101
102             // or maybe not... a PhiExpr may refer to a local that
103
// has not been seen yet in the pseudo topological order.
104
// use a stub node in that case and fill in the details later.
105
if(ret == null)
106                 ret = new Node(value, true);
107         }
108
109         // theoretically we could share Constant nodes...
110
else
111             ret = new Node(value);
112
113         return ret;
114     }
115
116     protected Node fetchGraph(Value value)
117     {
118         AbstractShimpleValueSwitch vs;
119         
120         value.apply(vs = new AbstractShimpleValueSwitch()
121         {
122             /**
123              * No default case, we implement explicit handling for
124              * each situation.
125              **/

126             public void defaultCase(Object JavaDoc object)
127             {
128                 throw new RuntimeException JavaDoc("Internal error: " + object +
129                                            " unhandled case.");
130             }
131             
132             /**
133              * Handle a trivial assignment.
134              **/

135             public void caseLocal(Local l)
136             {
137                 setResult(fetchNode(l));
138             }
139
140             /**
141              * Handle other simple assignments.
142              **/

143             public void handleConstant(Constant constant)
144             {
145                 setResult(fetchNode(constant));
146             }
147
148             /**
149              * Assume nothing about Refs.
150              **/

151             public void handleRef(Ref ref)
152             {
153                 setResult(fetchNode(ref));
154             }
155
156             public void handleBinop(BinopExpr binop, boolean ordered)
157             {
158                 Node nop1 = fetchNode(binop.getOp1());
159                 Node nop2 = fetchNode(binop.getOp2());
160
161                 List children = new ArrayList();
162                 children.add(nop1);
163                 children.add(nop2);
164
165                 setResult(new Node(binop, ordered, children));
166             }
167             
168             // *** FIXME
169
// *** assume non-equality by default
170
// *** what about New expressions?
171
public void handleUnknown(Expr expr)
172             {
173                 setResult(fetchNode(expr));
174             }
175             
176             public void handleUnop(UnopExpr unop)
177             {
178                 Node nop = fetchNode(unop.getOp());
179                 List child = new SingletonList(nop);
180                 setResult(new Node(unop, true, child));
181             }
182             
183
184             public void caseDoubleSwitch(DoubleConstant v)
185             {
186                 handleConstant(v);
187             }
188
189             public void caseFloatConstant(FloatConstant v)
190             {
191                 handleConstant(v);
192             }
193
194             public void caseIntConstant(IntConstant v)
195             {
196                 handleConstant(v);
197             }
198             
199             public void caseLongConstant(LongConstant v)
200             {
201                 handleConstant(v);
202             }
203
204             public void caseNullConstant(NullConstant v)
205             {
206                 handleConstant(v);
207             }
208
209             public void caseStringConstant(StringConstant v)
210             {
211                 handleConstant(v);
212             }
213
214             public void caseArrayRef(ArrayRef v)
215             {
216                 handleRef(v);
217             }
218
219             public void caseStaticFieldRef(StaticFieldRef v)
220             {
221                 handleRef(v);
222             }
223
224             public void caseInstanceFieldRef(InstanceFieldRef v)
225             {
226                 handleRef(v);
227             }
228
229             public void caseParameterRef(ParameterRef v)
230             {
231                 handleRef(v);
232             }
233
234             public void caseCaughtExceptionRef(CaughtExceptionRef v)
235             {
236                 handleRef(v);
237             }
238
239             public void caseThisRef(ThisRef v)
240             {
241                 handleRef(v);
242             }
243
244             public void caseAddExpr(AddExpr v)
245             {
246                 handleBinop(v, false);
247             }
248
249             public void caseAndExpr(AndExpr v)
250             {
251                 handleBinop(v, false);
252             }
253
254             public void caseCmpExpr(CmpExpr v)
255             {
256                 handleBinop(v, true);
257             }
258
259             public void caseCmpgExpr(CmpgExpr v)
260             {
261                 handleBinop(v, true);
262             }
263             
264             public void caseCmplExpr(CmplExpr v)
265             {
266                 handleBinop(v, true);
267             }
268             
269             public void caseDivExpr(DivExpr v)
270             {
271                 handleBinop(v, true);
272             }
273             
274             public void caseEqExpr(EqExpr v)
275             {
276                 handleBinop(v, false);
277             }
278                 
279             public void caseNeExpr(NeExpr v)
280             {
281                 handleBinop(v, false);
282             }
283             
284             public void caseGeExpr(GeExpr v)
285             {
286                 handleBinop(v, true);
287             }
288                 
289             public void caseGtExpr(GtExpr v)
290             {
291                 handleBinop(v, true);
292             }
293             
294             public void caseLeExpr(LeExpr v)
295             {
296                 handleBinop(v, true);
297             }
298             
299             public void caseLtExpr(LtExpr v)
300             {
301                 handleBinop(v, true);
302             }
303             
304             public void caseMulExpr(MulExpr v)
305             {
306                 handleBinop(v, false);
307             }
308
309             // *** check
310
public void caseOrExpr(OrExpr v)
311             {
312                 handleBinop(v, false);
313             }
314             
315             public void caseRemExpr(RemExpr v)
316             {
317                 handleBinop(v, true);
318             }
319             
320             public void caseShlExpr(ShlExpr v)
321             {
322                 handleBinop(v, true);
323             }
324             
325             public void caseShrExpr(ShrExpr v)
326             {
327                 handleBinop(v, true);
328             }
329             
330             public void caseUshrExpr(UshrExpr v)
331             {
332                 handleBinop(v, true);
333             }
334             
335             public void caseSubExpr(SubExpr v)
336             {
337                 handleBinop(v, true);
338             }
339
340             // *** check
341
public void caseXorExpr(XorExpr v)
342             {
343                 handleBinop(v, false);
344             }
345             
346             public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v)
347             {
348                 handleUnknown(v);
349             }
350
351             public void caseSpecialInvokeExpr(SpecialInvokeExpr v)
352             {
353                 handleUnknown(v);
354             }
355             
356             public void caseStaticInvokeExpr(StaticInvokeExpr v)
357             {
358                 handleUnknown(v);
359             }
360             
361             public void caseVirtualInvokeExpr(VirtualInvokeExpr v)
362             {
363                 handleUnknown(v);
364             }
365
366             /**
367              * Handle like a trivial assignment.
368              **/

369             public void caseCastExpr(CastExpr v)
370             {
371                 setResult(fetchNode(v.getOp()));
372             }
373
374             /**
375              * Handle like an ordered binop.
376              **/

377             public void caseInstanceOfExpr(InstanceOfExpr v)
378             {
379                 Node nop1 = fetchNode(v.getOp());
380
381                 Value op2 = new TypeValueWrapper(v.getCheckType());
382                 Node nop2 = fetchNode(op2);
383
384                 List children = new ArrayList();
385                 children.add(nop1);
386                 children.add(nop2);
387
388                 setResult(new Node(v, true, children));
389             }
390
391             // *** perhaps New expressions require special handling?
392
public void caseNewArrayExpr(NewArrayExpr v)
393             {
394                 handleUnknown(v);
395             }
396             
397             public void caseNewMultiArrayExpr(NewMultiArrayExpr v)
398             {
399                 handleUnknown(v);
400             }
401
402             public void caseNewExpr(NewExpr v)
403             {
404                 handleUnknown(v);
405             }
406
407             public void caseLengthExpr(LengthExpr v)
408             {
409                 handleUnop(v);
410             }
411
412             public void caseNegExpr(NegExpr v)
413             {
414                 handleUnop(v);
415             }
416
417             public void casePhiExpr(PhiExpr v)
418             {
419                 List children = new ArrayList();
420                 Iterator argsIt = v.getValues().iterator();
421
422                 while(argsIt.hasNext()){
423                     Value arg = (Value) argsIt.next();
424                     children.add(fetchNode(arg));
425                 }
426
427                 // relies on Phi nodes in same block having a
428
// consistent sort order...
429
setResult(new Node(v, true, children));
430             }
431         });
432
433         return((Node)vs.getResult());
434     }
435
436     public Node getNode(Value local)
437     {
438         return (Node) localToNode.get(local);
439     }
440
441     // *** Check for non-determinism
442
public Collection getTopNodes()
443     {
444         return localToNode.values();
445     }
446
447     public Local getLocal(Node node)
448     {
449         return (Local)nodeToLocal.get(node);
450     }
451
452     public String JavaDoc toString()
453     {
454         StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
455         
456         for(int i = 0; i < nodeList.size(); i++){
457             tmp.append(nodeList.get(i));
458             tmp.append("\n");
459         }
460
461         return tmp.toString();
462     }
463
464     // testing
465
public static void main(String JavaDoc[] args)
466     {
467         // assumes 2 args: Class + Method
468

469         Scene.v().loadClassAndSupport(args[0]);
470         SootClass sc = Scene.v().getSootClass(args[0]);
471         SootMethod sm = sc.getMethod(args[1]);
472         Body b = sm.retrieveActiveBody();
473         ShimpleBody sb = Shimple.v().newBody(b);
474         CompleteBlockGraph cfg = new CompleteBlockGraph(sb);
475         ValueGraph vg = new ValueGraph(cfg);
476         System.out.println(vg);
477     }
478
479     public class Node
480     {
481         protected int nodeNumber;
482         protected Value node;
483         protected String JavaDoc nodeLabel;
484         protected boolean ordered;
485         protected List children;
486
487         protected boolean stub = false;
488         
489         // stub node
490
protected Node(Value local, boolean ignored)
491         {
492             this.stub = true;
493             setNode(local);
494         }
495
496         protected void patchStubs()
497         {
498             // can't patch self
499
if(isStub())
500                 throw new RuntimeException JavaDoc("Assertion failed.");
501
502             // if any immediate children are stubs, patch them
503
for(int i = 0; i < children.size(); i++){
504                 Node child = (Node) children.get(i);
505
506                 if(child.isStub()){
507                     Node newChild = (Node) localToNode.get(child.node);
508                     if(newChild == null || newChild.isStub())
509                         throw new RuntimeException JavaDoc("Assertion failed.");
510                     children.set(i, newChild);
511                 }
512             }
513         }
514         
515         protected void checkIfStub()
516         {
517             if(isStub())
518                 throw new RuntimeException JavaDoc("Assertion failed: Attempted operation on invalid node (stub)");
519         }
520
521         protected Node(Value node)
522         {
523             this(node, true, Collections.EMPTY_LIST);
524         }
525
526         protected Node(Value node, boolean ordered, List children)
527         {
528             setNode(node);
529             setOrdered(ordered);
530             setChildren(children);
531
532             // updateLabel() relies on nodeNumber being set
533
nodeNumber = currentNodeNumber++;
534             updateLabel();
535             nodeList.add(nodeNumber, this);
536         }
537
538         protected void setNode(Value node)
539         {
540             this.node = node;
541         }
542         
543         protected void setOrdered(boolean ordered)
544         {
545             this.ordered = ordered;
546         }
547
548         protected void setChildren(List children)
549         {
550             this.children = children;
551         }
552
553         protected void updateLabel()
554         {
555             if(!children.isEmpty()){
556                 nodeLabel = node.getClass().getName();
557                 if(node instanceof PhiExpr)
558                     nodeLabel = nodeLabel + ((PhiExpr)node).getBlockId();
559             }
560             else{
561                 // *** FIXME
562

563                 // NewExpr
564
// NewArrayExpr
565
// NewMultiArrayExpr
566

567                 // Ref
568
// FieldRef?
569
// InstanceFieldRef?
570
// IdentityRef?
571
// ArrayRef?
572
// CaughtExceptionRef
573

574                 // InvokeExpr?
575
// InstanceInvokeExpr?
576
// InterfaceInvokeExpr?
577
// SpecialInvokeExpr
578
// StaticInvokeExpr
579
// VirtualInvokeExpr
580
nodeLabel = node.toString();
581                 if((node instanceof NewExpr) ||
582                    (node instanceof NewArrayExpr) ||
583                    (node instanceof NewMultiArrayExpr) ||
584                    (node instanceof Ref) ||
585                    (node instanceof InvokeExpr))
586                     nodeLabel = nodeLabel + " " + getNodeNumber();
587             }
588         }
589         
590         public boolean isStub()
591         {
592             return stub;
593         }
594
595         public String JavaDoc getLabel()
596         {
597             checkIfStub();
598             return nodeLabel;
599         }
600
601         public boolean isOrdered()
602         {
603             checkIfStub();
604             return ordered;
605         }
606
607         public List getChildren()
608         {
609             checkIfStub();
610             return children;
611             //return Collections.unmodifiableList(children);
612
}
613
614         public int getNodeNumber()
615         {
616             checkIfStub();
617             return nodeNumber;
618         }
619         
620         public String JavaDoc toString()
621         {
622             checkIfStub();
623
624             StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
625             
626             Local local = getLocal(this);
627             if(local != null)
628                 tmp.append(local.toString());
629             
630             tmp.append("\tNode " + getNodeNumber() + ": " + getLabel());
631
632             List children = getChildren();
633
634             if(!children.isEmpty()){
635                 tmp.append(" [" +
636                            (isOrdered() ? "ordered" : "unordered") + ": ");
637                 for(int i = 0; i < children.size(); i++){
638                     if(i != 0)
639                         tmp.append(", ");
640                     tmp.append(((Node) children.get(i)).getNodeNumber());
641                 }
642                 tmp.append("]");
643             }
644         
645             return tmp.toString();
646         }
647     }
648
649     protected static class TypeValueWrapper implements Value
650     {
651         protected Type type;
652
653         protected TypeValueWrapper(Type type)
654         {
655             this.type = type;
656         }
657
658         public List getUseBoxes()
659         {
660             return Collections.EMPTY_LIST;
661         }
662
663         public Type getType()
664         {
665             return type;
666         }
667
668         public Object JavaDoc clone()
669         {
670             return new TypeValueWrapper(type);
671         }
672
673         public void toString(UnitPrinter up)
674         {
675             up.literal("[Wrapped] " + type);
676         }
677
678         public void apply(Switch sw)
679         {
680             throw new RuntimeException JavaDoc("Not Implemented.");
681         }
682
683         public boolean equals(Object JavaDoc o)
684         {
685             if(!(o instanceof TypeValueWrapper))
686                 return false;
687
688             return getType().equals(((TypeValueWrapper)o).getType());
689         }
690
691         public int hashCode()
692         {
693             return getType().hashCode();
694         }
695
696         public boolean equivTo(Object JavaDoc o)
697         {
698             return equals(o);
699         }
700
701         public int equivHashCode()
702         {
703             return hashCode();
704         }
705     }
706 }
707
Popular Tags