OSDN Git Service

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