OSDN Git Service

opcodes を cflib に変更したことにともなう変更.
[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.List;
10 import java.util.Map;
11
12 import jp.sourceforge.stigmata.Birthmark;
13 import jp.sourceforge.stigmata.BirthmarkContext;
14 import jp.sourceforge.stigmata.BirthmarkElement;
15 import jp.sourceforge.stigmata.ExtractionUnit;
16 import jp.sourceforge.stigmata.birthmarks.ASMBirthmarkExtractor;
17 import jp.sourceforge.stigmata.birthmarks.BirthmarkElementBuilder;
18 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
19 import jp.sourceforge.stigmata.birthmarks.LabelOpcode;
20 import jp.sourceforge.stigmata.birthmarks.Opcode;
21 import jp.sourceforge.stigmata.birthmarks.OpcodeExtractVisitor;
22 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
23
24 import org.objectweb.asm.ClassWriter;
25 import org.objectweb.asm.Label;
26
27 /**
28  *
29  * @author Haruaki Tamada
30  * @version $Revision$
31  */
32 public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
33     public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
34         super(service);
35     }
36
37     @Override
38     public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkContext context){
39         return new OpcodeExtractVisitor(writer, birthmark, context, new WSPBirthmarkElementBuilder());
40     }
41
42     @Override
43     public ExtractionUnit[] getAcceptableUnits(){
44         return new ExtractionUnit[] {
45             ExtractionUnit.CLASS,
46         };
47     }
48
49     private static class WSPBirthmarkElementBuilder implements BirthmarkElementBuilder{
50         public BirthmarkElement[] buildElements(List<Opcode> opcodes, BirthmarkContext context){
51             List<CurrentDepth> pattern = buildStackPattern(opcodes, context);
52             List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
53
54             List<CurrentDepth> subPattern = new ArrayList<CurrentDepth>();
55             for(CurrentDepth depth: pattern){
56                 subPattern.add(depth);
57                 if(depth.getDepth() == 0){
58                     elements.add(new StackPatternBasedBirthmarkElement(subPattern.toArray(new CurrentDepth[subPattern.size()])));
59                     subPattern.clear();
60                 }
61             }
62             elements.add(new StackPatternBasedBirthmarkElement(subPattern.toArray(new CurrentDepth[subPattern.size()])));
63
64             return elements.toArray(new BirthmarkElement[elements.size()]);
65         }
66
67         @SuppressWarnings("unchecked")
68         private List<CurrentDepth> buildStackPattern(List<Opcode> opcodes, BirthmarkContext context){
69             Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
70             List<CurrentDepth> pattern = new ArrayList<CurrentDepth>();
71             Map<Integer, Integer> weights = (Map<Integer, Integer>)context.getProperty("birthmarks.wsp.weights");
72
73             int currentDepth = 0;
74             Integer forwardedStatus = null;
75             for(Opcode opcode: opcodes){
76                 if(opcode.getCategory() == Opcode.Category.TARGETER){
77                     forwardedStatus = tableMap.get(((LabelOpcode)opcode).getLabel());
78                 }
79                 else{
80                     WSPOpcode wspOpcode = new WSPOpcode(opcode, weights.get(opcode.getOpcode()));
81                     if(forwardedStatus == null){
82                         currentDepth += opcode.getAct();
83                     }
84                     else{
85                         currentDepth = forwardedStatus + opcode.getAct();
86                     }
87                     forwardedStatus = null;
88
89                     pattern.add(new CurrentDepth(currentDepth, wspOpcode));
90                     if(opcode.getCategory() == Opcode.Category.BRANCH){
91                         for(Label label: opcode.getLabels()){
92                             tableMap.put(label, currentDepth);
93                         }
94                     }
95                 }
96             }
97             return pattern;
98         }
99     };
100 }