OSDN Git Service

514633e785d94b5e30cfa435de8b0bb4cba55088
[stigmata/stigmata-plugins.git] / wsp / src / main / java / jp / sourceforge / stigmata / birthmarks / wsp / StackPatternBasedBirthmarkExtractor.java
1 package jp.sourceforge.stigmata.birthmarks.wsp;
2
3 /*
4  * $Id$
5  */
6
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12
13 import jp.sourceforge.stigmata.Birthmark;
14 import jp.sourceforge.stigmata.BirthmarkContext;
15 import jp.sourceforge.stigmata.BirthmarkElement;
16 import jp.sourceforge.stigmata.ExtractionUnit;
17 import jp.sourceforge.stigmata.birthmarks.ASMBirthmarkExtractor;
18 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
19 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
20
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.ClassWriter;
23 import org.objectweb.asm.Label;
24 import org.objectweb.asm.MethodVisitor;
25
26 /**
27  * 
28  * @author Haruaki Tamada
29  * @version $Revision$
30  */
31 public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
32     public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
33         super(service);
34     }
35
36     @Override
37     public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkContext context){
38         return new Visitor(writer, birthmark, context);
39     }
40
41     @Override
42     public ExtractionUnit[] getAcceptableUnits(){
43         return new ExtractionUnit[] {
44             ExtractionUnit.CLASS,
45         };
46     }
47
48     private BirthmarkElement[] buildElement(List<Opcode> opcodes, BirthmarkContext context){
49         List<CurrentDepth> pattern = buildStackPattern(opcodes, context);
50         List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
51
52         List<CurrentDepth> subPattern = new ArrayList<CurrentDepth>();
53         for(CurrentDepth depth: pattern){
54             subPattern.add(depth);
55             if(depth.getDepth() == 0){
56                 elements.add(new StackPatternBasedBirthmarkElement(subPattern.toArray(new CurrentDepth[subPattern.size()])));
57                 subPattern.clear();
58             }
59         }
60         elements.add(new StackPatternBasedBirthmarkElement(subPattern.toArray(new CurrentDepth[subPattern.size()])));
61
62         return elements.toArray(new BirthmarkElement[elements.size()]);
63     }
64
65     @SuppressWarnings("unchecked")
66     private List<CurrentDepth> buildStackPattern(List<Opcode> opcodes, BirthmarkContext context){ 
67         Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
68         List<CurrentDepth> pattern = new ArrayList<CurrentDepth>();
69         Map<Integer, Integer> weights = (Map<Integer, Integer>)context.getProperty("birthmarks.wsp.weights");
70
71         int currentDepth = 0;
72         Integer forwardedStatus = null;
73         for(Opcode opcode: opcodes){
74             opcode.setWeight(weights.get(opcode.getOpcode()));
75             if(opcode.getCategory() == Opcode.Category.TARGETER){
76                 forwardedStatus = tableMap.get(((LabelOpcode)opcode).getLabel());
77             }
78             else{
79                 if(forwardedStatus == null){
80                     currentDepth += opcode.getAct();
81                 }
82                 else{
83                     currentDepth = forwardedStatus + opcode.getAct(); 
84                 }
85                 forwardedStatus = null;
86
87                 pattern.add(new CurrentDepth(currentDepth, opcode));
88                 if(opcode.getCategory() == Opcode.Category.BRANCH){
89                     for(Iterator<Label> i = opcode.labels(); i.hasNext(); ){
90                         Label label = i.next();
91                         tableMap.put(label, currentDepth);
92                     }
93                 }
94             }
95         }
96         return pattern;
97     }
98
99     private class Visitor extends BirthmarkExtractVisitor{
100         private List<Opcode> opcodeList = new ArrayList<Opcode>();
101
102         public Visitor(ClassVisitor visitor, Birthmark birthmark, BirthmarkContext context){
103             super(visitor, birthmark, context);
104         }
105
106         public void visitEnd(){
107             BirthmarkElement[] elements = buildElement(opcodeList, getContext());
108             for(BirthmarkElement element: elements){
109                 addElement(element);
110             }
111         }
112
113         @Override
114         public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4){
115             MethodVisitor visitor = super.visitMethod(arg0, arg1, arg2, arg3, arg4);
116             OpcodeExtractionMethodVisitor opcodeVisitor = new OpcodeExtractionMethodVisitor(visitor, opcodeList);
117
118             return opcodeVisitor;
119         }
120     };
121
122
123 }