OSDN Git Service

update
[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.BirthmarkElementBuilder;
19 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
20 import jp.sourceforge.stigmata.birthmarks.LabelOpcode;
21 import jp.sourceforge.stigmata.birthmarks.Opcode;
22 import jp.sourceforge.stigmata.birthmarks.OpcodeExtractVisitor;
23 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
24
25 import org.objectweb.asm.ClassWriter;
26 import org.objectweb.asm.Label;
27
28 /**
29  *
30  * @author Haruaki Tamada
31  * @version $Revision$
32  */
33 public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
34     public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
35         super(service);
36     }
37
38     @Override
39     public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkContext context){
40         return new OpcodeExtractVisitor(writer, birthmark, context, new WSPBirthmarkElementBuilder());
41     }
42
43     @Override
44     public ExtractionUnit[] getAcceptableUnits(){
45         return new ExtractionUnit[] {
46             ExtractionUnit.CLASS,
47         };
48     }
49
50     private static class WSPBirthmarkElementBuilder implements BirthmarkElementBuilder{
51         public BirthmarkElement[] buildElements(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                     WSPOpcode wspOpcode = new WSPOpcode(opcode, 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, wspOpcode));
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 }