OSDN Git Service

cflib は plugins プロジェクトから,Stigmata直下のプロジェクトに移行したため,このリポジトリからは削除した.
[stigmata/stigmata-plugins.git] / osb / src / main / java / jp / sourceforge / stigmata / birthmarks / osb / OperandStackBehaviorsBirthmarkExtractor.java
1 package jp.sourceforge.stigmata.birthmarks.osb;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import jp.sourceforge.stigmata.Birthmark;
9 import jp.sourceforge.stigmata.BirthmarkContext;
10 import jp.sourceforge.stigmata.BirthmarkElement;
11 import jp.sourceforge.stigmata.ExtractionUnit;
12 import jp.sourceforge.stigmata.birthmarks.ASMBirthmarkExtractor;
13 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
14 import jp.sourceforge.stigmata.cflib.BirthmarkElementBuilder;
15 import jp.sourceforge.stigmata.cflib.LabelOpcode;
16 import jp.sourceforge.stigmata.cflib.Opcode;
17 import jp.sourceforge.stigmata.cflib.OpcodeExtractVisitor;
18 import jp.sourceforge.stigmata.cflib.OpcodeManager;
19 import jp.sourceforge.stigmata.spi.BirthmarkService;
20
21 import org.objectweb.asm.ClassWriter;
22 import org.objectweb.asm.Label;
23
24 /**
25  * Operand Stack Behavior を抽出するためのクラス.
26  *
27  * @author Fumiya Iwama
28  * @author Ryouta Obatake
29  * @author Akinori Kataoka
30  * @author Takayuki Kitano
31  */
32 public class OperandStackBehaviorsBirthmarkExtractor extends ASMBirthmarkExtractor{
33         
34     public OperandStackBehaviorsBirthmarkExtractor(BirthmarkService service){
35         super(service);
36     }
37
38     @Override
39     public BirthmarkExtractVisitor createExtractVisitor(
40             ClassWriter writer, Birthmark birthmark,
41             BirthmarkContext context){
42                 
43         return new OpcodeExtractVisitor(writer, birthmark, context, new OSBBirthmarkElementBuilder());
44     }
45
46     @Override
47     public ExtractionUnit[] getAcceptableUnits(){
48         return new ExtractionUnit[] {
49             ExtractionUnit.CLASS,
50         };
51     }
52     
53     private static class OSBBirthmarkElementBuilder implements BirthmarkElementBuilder{
54         @Override
55         public BirthmarkElement[] buildElements(List<Opcode> opcodes,
56                                                 BirthmarkContext context){
57             List<CurrentDepth> pattern = buildStackPattern(opcodes, context);
58             List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
59
60             List<Opcode> subPattern = new ArrayList<Opcode>();
61             for(CurrentDepth depth: pattern){
62                 subPattern.add(depth.getOpcode());
63                 if(depth.getDepth() == 0){//深さが0になるごとに、behaviorを区切る
64                     elements.add(new OperandStackBehaviorsBirthmarkElement(
65                         subPattern.toArray(new Opcode[subPattern.size()])
66                     ));
67                     subPattern.clear();
68                 }
69             }
70
71             if(subPattern.size() != 0){//これで無駄な空白を除去
72                 elements.add(new OperandStackBehaviorsBirthmarkElement(
73                     subPattern.toArray(new Opcode[subPattern.size()])
74                 ));
75             }
76
77             return elements.toArray(new BirthmarkElement[elements.size()]);
78         }
79
80         private List<CurrentDepth> buildStackPattern(List<Opcode> opcodes, BirthmarkContext context){
81             Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
82             List<CurrentDepth> pattern = new ArrayList<CurrentDepth>();
83
84             int currentDepth = 0;
85             Integer forwardedStatus = null;
86             for(Opcode opcode: opcodes){
87                 if(opcode.getCategory() == Opcode.Category.TARGETER){
88                     forwardedStatus =
89                         tableMap.get(((LabelOpcode)opcode).getLabel());
90                 }
91                 else{
92                     if(forwardedStatus == null){
93                         currentDepth += opcode.getAct();
94                     }
95                     else{
96                         currentDepth = forwardedStatus + opcode.getAct();
97                     }
98                     forwardedStatus = null;
99
100                     pattern.add(new CurrentDepth(currentDepth, opcode));
101                     if(opcode.getCategory() == Opcode.Category.BRANCH){
102                         for(Label label: opcode.getLabels()){
103                             tableMap.put(label, currentDepth);
104                         }
105                     }
106                 }
107             }
108             return pattern;
109         }
110     }
111     
112     @Override
113     public BirthmarkElement buildElement(String value){
114         OpcodeManager manager = OpcodeManager.getInstance();
115         String[] elements = value.split(", ");
116         Opcode[] opcodes = new Opcode[elements.length];
117         for(int i = 0; i < opcodes.length; i++){
118             opcodes[i] = manager.getOpcode(Integer.parseInt(elements[i]));
119         }
120         return new OperandStackBehaviorsBirthmarkElement(opcodes);
121     }; 
122 }